commit 78e95549f032f0e3dfe2138d9102184b253cc50f Author: nitrogenoliquido <203537016+nitrogenoliquido@users.noreply.github.com> Date: Mon Nov 2 17:46:49 2026 -0500 added files. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..62fa0a4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +.gradle/ +build/ +out/ +.idea/ +*.iml +.classpath +.project +.settings/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..b267f6c --- /dev/null +++ b/README.md @@ -0,0 +1,43 @@ +

+ Skid Solutions Banner +
+ OpenAllatori +
+ by Skid Solutions +

+ +--- + +

+ https://discord.gg/AEwatvnvSf +

+ +

+ jak + hack + deobf2 + deobf +

+ +--- + +## How to build + +### Prerequisites +- **Java Development Kit**: JDK 17 (the Gradle wrapper 8.14.3 does not run on newer JDKs) + +--- + +### Building OpenAllatori + +Run from this folder: + +```powershell +$env:JAVA_HOME = "C:\Program Files\Java\jdk-17" + +.\gradlew.bat clean build +``` + +Generated `build/libs/`: +- `OpenAllatori-9.9.jar` +- `OpenAllatori-9.9-sources.jar` diff --git a/assets/deobf.jpg b/assets/deobf.jpg new file mode 100644 index 0000000..fa8dbde Binary files /dev/null and b/assets/deobf.jpg differ diff --git a/assets/deobf2.png b/assets/deobf2.png new file mode 100644 index 0000000..1d4014d Binary files /dev/null and b/assets/deobf2.png differ diff --git a/assets/hack.jpg b/assets/hack.jpg new file mode 100644 index 0000000..c4252ef Binary files /dev/null and b/assets/hack.jpg differ diff --git a/assets/jak.jpg b/assets/jak.jpg new file mode 100644 index 0000000..162bfe5 Binary files /dev/null and b/assets/jak.jpg differ diff --git a/assets/ss.png b/assets/ss.png new file mode 100644 index 0000000..041b33a Binary files /dev/null and b/assets/ss.png differ diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..b4df1f6 --- /dev/null +++ b/build.gradle @@ -0,0 +1,53 @@ +plugins { + id 'java' + id 'application' + id 'idea' + id 'eclipse' +} +group = 'com.allatori' +version = '9.9' +repositories { mavenCentral() } +java { + toolchain.languageVersion = JavaLanguageVersion.of(17) + withSourcesJar() +} +application { + mainClass = 'com.allatori.Obfuscate' + applicationDefaultJvmArgs = ['--add-opens=java.base/java.util.zip=ALL-UNNAMED'] +} +sourceSets { + wtkApi { java.srcDir 'src/wtkApi/java' } + main { compileClasspath += sourceSets.wtkApi.output } +} +dependencies { + compileOnly 'org.apache.ant:ant:1.10.15' + compileOnly('org.eclipse.platform:org.eclipse.equinox.registry:3.11.200') { transitive = false } + compileOnly('org.eclipse.platform:org.eclipse.core.resources:3.18.100') { transitive = false } + compileOnly('org.eclipse.platform:org.eclipse.core.runtime:3.26.100') { transitive = false } + compileOnly('org.eclipse.platform:org.eclipse.equinox.common:3.17.0') { transitive = false } + compileOnly('org.eclipse.platform:org.eclipse.core.jobs:3.13.200') { transitive = false } + compileOnly('org.eclipse.platform:org.eclipse.core.commands:3.10.300') { transitive = false } + compileOnly('org.eclipse.platform:org.eclipse.core.expressions:3.8.200') { transitive = false } + compileOnly('org.eclipse.platform:org.eclipse.jface:3.28.0') { transitive = false } + compileOnly('org.eclipse.platform:org.eclipse.ui.workbench:3.127.0') { transitive = false } + compileOnly('org.eclipse.platform:org.eclipse.osgi:3.18.200') { transitive = false } + compileOnly('org.eclipse.jdt:org.eclipse.jdt.core:3.32.0') { transitive = false } +} +tasks.named('compileJava') { dependsOn tasks.named('wtkApiClasses') } +tasks.withType(JavaCompile).configureEach { + options.release = 17 + options.encoding = 'UTF-8' + options.compilerArgs += ['-parameters', '-Xmaxerrs', '2000'] +} +tasks.withType(AbstractArchiveTask).configureEach { + preserveFileTimestamps = false + reproducibleFileOrder = true +} +jar { + manifest { + from('src/main/resources/META-INF/MANIFEST.MF') + attributes('Main-Class': 'com.allatori.Obfuscate', 'Bundle-RequiredExecutionEnvironment': 'JavaSE-17', 'Add-Opens': 'java.base/java.util.zip') + } +} +processResources { exclude 'META-INF/MANIFEST.MF' } +tasks.register('resolveCompileApis') { doLast { configurations.compileClasspath.files.each { println it.name } } } diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..20c1f45 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,2 @@ +org.gradle.jvmargs=-Xmx3g -Dfile.encoding=UTF-8 +org.gradle.workers.max=2 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..1b33c55 Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..9251069 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,8 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionSha256Sum=bd71102213493060956ec229d946beee57158dbd89d0e62b91bca0fa2c5f3531 diff --git a/gradlew b/gradlew new file mode 100644 index 0000000..23d15a9 --- /dev/null +++ b/gradlew @@ -0,0 +1,251 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH="\\\"\\\"" + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..db3a6ac --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,94 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH= + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..96815be --- /dev/null +++ b/settings.gradle @@ -0,0 +1,7 @@ +pluginManagement { + repositories { + mavenCentral() + gradlePluginPortal() + } +} +rootProject.name = 'OpenAllatori' diff --git a/src/main/java/com/allatori/Obfuscate.java b/src/main/java/com/allatori/Obfuscate.java new file mode 100644 index 0000000..b774b61 --- /dev/null +++ b/src/main/java/com/allatori/Obfuscate.java @@ -0,0 +1,75 @@ +package com.allatori; + +import com.allatori.cli.ObfuscationCommandSupport; +import com.allatori.config.Configuration; +import com.allatori.engine.ObfuscationEngine; +import com.allatori.engine.ObfuscationException; +import com.allatori.model.ClassStorage; +import com.allatori.naming.MappingXmlWriter; +import com.allatori.util.Log; +import java.io.File; +import java.io.IOException; + +public class Obfuscate extends ObfuscationCommandSupport { + + public static void obfuscate(ClassStorage classStorage) { + new ObfuscationEngine(classStorage).obfuscate(); + } + + public static void runObfuscation() + throws IOException, ObfuscationException, ClassNotFoundException { + ClassStorage classStorage; + obfuscate(classStorage = createClassStorage()); + if (Configuration.getWatermarkOptions().getText2() != null + && Configuration.getWatermarkOptions().getText() != null) { + addWatermark(classStorage); + } + if (Configuration.getObfuscationOptions().isJava6Enabled()) { + limitClassVersion(classStorage); + } + writeAllOutputs(classStorage); + Log.info2("Obfuscation completed. Writing log file..."); + MappingXmlWriter.update(); + } + + public static void main(String[] texts) { + String[] texts2; + if (texts.length > 1 && "-silent".equals(texts[1])) { + Log.setSilent(true); + texts2 = texts; + } else { + System.out.println(getBanner()); + texts2 = texts; + } + if (texts2.length != 1 && !Log.isSilent()) { + printUsage(); + System.exit(0); + } + if (!loadConfigurationSafely(texts[0])) { + System.exit(-1); + } + try { + runObfuscation(); + } catch (Exception exception) { + Log.error(exception.getMessage()); + System.out.println( + "############### EXCEPTION (" + VersionInfo.getVersion() + ") ###############"); + exception.printStackTrace(); + System.out.println("#################################################"); + System.exit(-1); + } + Configuration.update(); + } + + public static void printUsage() { + System.out.println("" + VersionInfo.getProductName() + " " + VersionInfo.getVersion()); + System.out.println("Usage:"); + System.out.println("com.allatori.Obfuscate "); + } + + public static void run(File file) throws Exception { + loadConfiguration(file.getPath()); + runObfuscation(); + Configuration.update(); + } +} diff --git a/src/main/java/com/allatori/StackTrace.java b/src/main/java/com/allatori/StackTrace.java new file mode 100644 index 0000000..1fff540 --- /dev/null +++ b/src/main/java/com/allatori/StackTrace.java @@ -0,0 +1,109 @@ +package com.allatori; + +import com.allatori.cli.ObfuscationCommandSupport; +import com.allatori.stacktrace.MappingXmlReader; +import com.allatori.stacktrace.StackTraceMappings; +import com.allatori.stacktrace.StackTraceRestorer; +import com.allatori.util.Log; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.io.StringReader; +import java.io.StringWriter; +import java.io.UnsupportedEncodingException; +import javax.xml.parsers.ParserConfigurationException; +import org.xml.sax.SAXException; + +public class StackTrace { + + public static void printUsage() { + System.out.println("Restore Stack Trace Utility"); + System.out.println("Usage:"); + System.out.println("com.allatori.StackTrace "); + } + + public static String restoreStackTrace(File file, String text) + throws FileNotFoundException, + UnsupportedEncodingException, + IOException, + ParserConfigurationException, + SAXException { + StackTraceMappings stackTraceMappings = + MappingXmlReader.createStackTraceMappings( + new InputStreamReader(new FileInputStream(file), "UTF-8")); + BufferedReader bufferedReader = new BufferedReader(new StringReader(text)); + StringWriter stringWriter = new StringWriter(); + PrintWriter printWriter = new PrintWriter(stringWriter); + StackTraceRestorer.processPrintWriter(bufferedReader, stackTraceMappings, printWriter); + bufferedReader.close(); + printWriter.close(); + return stringWriter.toString(); + } + + public static void main(String[] texts) { + BufferedReader bufferedReader; + System.out.println(ObfuscationCommandSupport.getBanner()); + try { + if (texts.length != 3) { + printUsage(); + System.exit(0); + } + StackTraceMappings stackTraceMappings = null; + String text = texts[0]; + String[] texts2; + label39: + { + try { + stackTraceMappings = + MappingXmlReader.createStackTraceMappings( + new InputStreamReader(new FileInputStream(text), "UTF-8")); + } catch (FileNotFoundException fileNotFoundException) { + Log.error("Log file not found: " + fileNotFoundException.getMessage()); + System.exit(0); + texts2 = texts; + break label39; + } catch (Exception exception) { + Log.error("Error reading log file: " + exception.getMessage()); + System.exit(0); + texts2 = texts; + break label39; + } + texts2 = texts; + } + String text2 = texts2[1]; + String text3 = texts[2]; + BufferedReader bufferedReader2 = null; + try { + bufferedReader2 = new BufferedReader(new FileReader(text2)); + } catch (FileNotFoundException fileNotFoundException2) { + Log.error("Input file not found: " + fileNotFoundException2.getMessage()); + System.exit(0); + } + PrintWriter printWriter = null; + label34: + { + try { + printWriter = new PrintWriter(new BufferedWriter(new FileWriter(text3))); + } catch (IOException oException) { + Log.error("Error writing output file: " + oException.getMessage()); + System.exit(0); + bufferedReader = bufferedReader2; + break label34; + } + bufferedReader = bufferedReader2; + } + StackTraceRestorer.processPrintWriter(bufferedReader, stackTraceMappings, printWriter); + bufferedReader2.close(); + printWriter.close(); + } catch (Exception exception2) { + System.out.println("Error: " + exception2.getMessage()); + } + } +} diff --git a/src/main/java/com/allatori/StackTrace2.java b/src/main/java/com/allatori/StackTrace2.java new file mode 100644 index 0000000..6dd3f9f --- /dev/null +++ b/src/main/java/com/allatori/StackTrace2.java @@ -0,0 +1,109 @@ +package com.allatori; + +import com.allatori.cli.ObfuscationCommandSupport; +import com.allatori.stacktrace.MappingXmlReader; +import com.allatori.stacktrace.StackTraceMappings; +import com.allatori.stacktrace.StackTraceRestorer; +import com.allatori.util.Log; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.io.StringReader; +import java.io.StringWriter; +import java.io.UnsupportedEncodingException; +import javax.xml.parsers.ParserConfigurationException; +import org.xml.sax.SAXException; + +public class StackTrace2 { + + public static String restoreStackTrace(File file, String text) + throws FileNotFoundException, + UnsupportedEncodingException, + IOException, + ParserConfigurationException, + SAXException { + StackTraceMappings stackTraceMappings = + MappingXmlReader.createStackTraceMappings( + new InputStreamReader(new FileInputStream(file), "UTF-8")); + BufferedReader bufferedReader = new BufferedReader(new StringReader(text)); + StringWriter stringWriter = new StringWriter(); + PrintWriter printWriter = new PrintWriter(stringWriter); + StackTraceRestorer.processPrintWriter2(bufferedReader, stackTraceMappings, printWriter); + bufferedReader.close(); + printWriter.close(); + return stringWriter.toString(); + } + + public static void printUsage() { + System.out.println("Restore Stack Trace Utility"); + System.out.println("Usage:"); + System.out.println("com.allatori.StackTrace2 "); + } + + public static void main(String[] texts) { + BufferedReader bufferedReader; + System.out.println(ObfuscationCommandSupport.getBanner()); + try { + if (texts.length != 3) { + printUsage(); + System.exit(0); + } + StackTraceMappings stackTraceMappings = null; + String text = texts[0]; + String[] texts2; + label39: + { + try { + stackTraceMappings = + MappingXmlReader.createStackTraceMappings( + new InputStreamReader(new FileInputStream(text), "UTF-8")); + } catch (FileNotFoundException fileNotFoundException) { + Log.error("Log file not found: " + fileNotFoundException.getMessage()); + System.exit(0); + texts2 = texts; + break label39; + } catch (Exception exception) { + Log.error("Error reading log file: " + exception.getMessage()); + System.exit(0); + texts2 = texts; + break label39; + } + texts2 = texts; + } + String text2 = texts2[1]; + String text3 = texts[2]; + BufferedReader bufferedReader2 = null; + try { + bufferedReader2 = new BufferedReader(new FileReader(text2)); + } catch (FileNotFoundException fileNotFoundException2) { + Log.error("Input file not found: " + fileNotFoundException2.getMessage()); + System.exit(0); + } + PrintWriter printWriter = null; + label34: + { + try { + printWriter = new PrintWriter(new BufferedWriter(new FileWriter(text3))); + } catch (IOException oException) { + Log.error("Error writing output file: " + oException.getMessage()); + System.exit(0); + bufferedReader = bufferedReader2; + break label34; + } + bufferedReader = bufferedReader2; + } + StackTraceRestorer.processPrintWriter2(bufferedReader, stackTraceMappings, printWriter); + bufferedReader2.close(); + printWriter.close(); + } catch (Exception exception2) { + System.out.println("Error: " + exception2.getMessage()); + } + } +} diff --git a/src/main/java/com/allatori/VersionInfo.java b/src/main/java/com/allatori/VersionInfo.java new file mode 100644 index 0000000..8958e97 --- /dev/null +++ b/src/main/java/com/allatori/VersionInfo.java @@ -0,0 +1,16 @@ +package com.allatori; + +public class VersionInfo { + + public static String getProductName() { + return "OpenAllatori"; + } + + public static String getVersion() { + return "v9.9"; + } + + public static String getWebsite() { + return "https://github.com/Skid-Technology"; + } +} diff --git a/src/main/java/com/allatori/Watermark.java b/src/main/java/com/allatori/Watermark.java new file mode 100644 index 0000000..bf0dcc3 --- /dev/null +++ b/src/main/java/com/allatori/Watermark.java @@ -0,0 +1,65 @@ +package com.allatori; + +import com.allatori.cli.ObfuscationCommandSupport; +import com.allatori.config.Configuration; +import com.allatori.model.ClassStorage; +import com.allatori.util.Log; + +public class Watermark extends ObfuscationCommandSupport { + + public static void main(String[] texts) { + System.out.println(getBanner()); + if (texts.length != 2) { + printUsage(); + System.exit(0); + } + byte value = 0; + String[] texts2; + if ("-add".equals(texts[0])) { + value = 0; + texts2 = texts; + } else if ("-extract".equals(texts[0])) { + value = 1; + texts2 = texts; + } else { + printUsage(); + System.exit(0); + texts2 = texts; + } + if (!loadConfigurationSafely(texts2[1], value != 0)) { + System.exit(-1); + } + try { + ClassStorage classStorage = Obfuscate.createClassStorage(); + if (Configuration.getWatermarkOptions().isEnabled()) { + if (Configuration.getWatermarkOptions().getText2() == null) { + Log.error("Configuration error. Watermark key is not set."); + System.exit(0); + } + System.out.println("Extracted watermark: \"" + extractWatermark(classStorage) + "\""); + } else { + if (Configuration.getWatermarkOptions().getText2() == null) { + Log.error("Configuration error. Watermark key is not set."); + System.exit(0); + } + if (Configuration.getWatermarkOptions().getText() == null) { + Log.error("Configuration error. Watermark value is not set."); + System.exit(0); + } + addWatermark(classStorage); + writeAllOutputs(classStorage); + } + } catch (Exception exception) { + Log.error(exception.getMessage()); + } + Configuration.update(); + } + + public static void printUsage() { + System.out.println("" + VersionInfo.getProductName() + " " + VersionInfo.getVersion()); + System.out.println("Usage:"); + System.out.println("com.allatori.Watermark -add "); + System.out.println("or"); + System.out.println("com.allatori.Watermark -extract "); + } +} diff --git a/src/main/java/com/allatori/ant/ObfuscatorTask.java b/src/main/java/com/allatori/ant/ObfuscatorTask.java new file mode 100644 index 0000000..252eab1 --- /dev/null +++ b/src/main/java/com/allatori/ant/ObfuscatorTask.java @@ -0,0 +1,39 @@ +package com.allatori.ant; + +import com.allatori.Obfuscate; +import com.allatori.config.Configuration; +import com.allatori.util.FileUtils; +import java.io.File; +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Task; + +public class ObfuscatorTask extends Task { + + public String config; + + public void execute() { + if (this.config == null) { + throw new BuildException("Missing 'config' attribute."); + } + try { + File file; + if (!(file = new File(this.config)).canRead()) { + throw new BuildException(("Cannot find configuration file: '" + this.config + "'")); + } + File file2 = new File(("" + this.config + ".resolved")); + file2.deleteOnExit(); + String text = FileUtils.createText(file, "UTF-8"); + String text2 = this.getProject().replaceProperties(text); + FileUtils.processText(file2, "UTF-8", text2); + Configuration.processText(file2.getPath()); + Obfuscate.runObfuscation(); + Configuration.update(); + } catch (Exception exception) { + throw new BuildException(exception); + } + } + + public void setConfig(String config) { + this.config = config; + } +} diff --git a/src/main/java/com/allatori/bytecode/ClassHierarchy.java b/src/main/java/com/allatori/bytecode/ClassHierarchy.java new file mode 100644 index 0000000..2e1c0c1 --- /dev/null +++ b/src/main/java/com/allatori/bytecode/ClassHierarchy.java @@ -0,0 +1,336 @@ +package com.allatori.bytecode; + +import com.allatori.config.Configuration; +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.lib.bcel.generic.MethodGen$2; +import com.allatori.lib.bcel.generic.Type; +import com.allatori.model.ClassStorage; +import com.allatori.util.Log; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.Collections; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.Set; +import java.util.TreeSet; +import java.util.Vector; + +public class ClassHierarchy { + + public Hashtable entries; + + public Hashtable entries2; + + public Vector values; + + public static final String TEXT = "-=404=-"; + + public static final Vector VALUES = new Vector(); + + public static final Set VALUES2 = new OrderedClassSet(); + + public ClassStorage classStorage; + + public Set values2; + + public Set createValues(Set values) { + if (values.contains("-=404=-")) { + return VALUES2; + } + TreeSet treeSet = new TreeSet(); + for (String text : ((Iterable) ((Iterable) values))) { + if (this.classStorage.getClassGen(text) == null) { + try { + Method[] methods; + for (int value = + (methods = + Class.forName(text, false, this.classStorage.getClassLoader()) + .getDeclaredMethods()) + .length + - 1; + value >= 0; + value--) { + Method method = methods[value]; + if (this.matchesMethod(method)) { + treeSet.add(method.getName() + "&" + Type.getSignature(method)); + } + } + } catch (ClassNotFoundException classNotFoundException) { + } catch (NoClassDefFoundError noClassDefFoundError) { + String text2; + if ((text2 = noClassDefFoundError.getMessage()).length() > 0) { + String text3 = text2.replace('/', '.'); + if (!this.entries.containsKey(text3)) { + this.entries.put(text3, ""); + Log.warn("Class '" + text3 + "' cannot be found."); + } + } + } catch (VerifyError verifyError) { + Log.warn( + "Cannot read class. Possible JVM compile and runtime versions mismatch: " + + verifyError.getMessage()); + } + } else { + int value2; + if (Configuration.getIgnoreClassesOptions() + .matchesClassGen(this.classStorage, this.classStorage.getClassGen(text))) { + com.allatori.lib.bcel.classfile.Method[] methods2; + for (int value3 = + value2 = (methods2 = this.classStorage.getClassGen(text).getMethods()).length - 1; + value3 >= 0; + value3 = --value2) { + com.allatori.lib.bcel.classfile.Method method2; + if (!(method2 = methods2[value2]).isEnabled9() && !method2.isEnabled11()) { + treeSet.add("" + method2.getText() + "&" + method2.getText2()); + } + } + } + } + } + return treeSet; + } + + public void processClassGen(ClassGen classGen) { + this.values.remove(classGen); + this.values.add(0, classGen); + String superclassName = classGen.getSuperclassName(); + ClassGen classGen2 = this.classStorage.getClassGen(superclassName); + if (classGen2 != null) { + this.processClassGen(classGen2); + } + String[] texts; + int value; + for (int value2 = value = (texts = classGen.getInterfaceNames()).length - 1; + value2 >= 0; + value2 = --value) { + ClassGen classGen3; + if ((classGen3 = this.classStorage.getClassGen(texts[value])) != null) { + this.processClassGen(classGen3); + } + } + } + + public void update() { + Hashtable hashtable = new Hashtable(); + int value; + for (int value2 = value = 0; value2 < this.values.size(); value2 = ++value) { + ClassGen classGen = (ClassGen) this.values.get(value); + hashtable.put(classGen, ""); + Vector values2 = this.getValues(classGen.getClassName()); + int value3 = 0; + for (int value4 = value3; value4 < values2.size(); value4 = ++value3) { + ClassGen classGen2 = (ClassGen) values2.get(value3); + if (hashtable.containsKey(classGen2)) { + Log.error("Incorrect classes order"); + } + } + } + } + + public boolean matchesText(String text, String text2, String text3) { + return this.values2.contains("" + text + "&" + text2 + "&" + text3); + } + + public void processClassGen2(ClassGen classGen) { + Set values = this.createValues(classGen); + Set values3; + Set values4 = this.createValues(values3 = this.createValues2(classGen)); + Iterator iterator2; + Iterator iterator3 = iterator2 = this.createValues(values, values4).iterator(); + while (iterator3.hasNext()) { + Set values5 = this.values2; + StringBuilder stringBuilder = + new StringBuilder().insert(0, classGen.getClassName()).append("&"); + iterator3 = iterator2; + values5.add(stringBuilder.append(iterator2.next()).toString()); + } + this.processValues(values3, values4); + } + + public void update2() { + Vector vector = new Vector(); + Iterator iterator; + Iterator iterator2 = iterator = this.classStorage.getClassesByName2(); + while (iterator2.hasNext()) { + iterator2 = iterator; + vector.add(iterator.next()); + } + Collections.sort(vector, new ClassHierarchyComparator(this)); + this.values = new Vector(); + for (ClassGen classGen : ((Iterable) ((Iterable) vector))) { + if (this.getValues(classGen.getClassName()).size() == 0) { + this.processClassGen(classGen); + } + } + Collections.sort(this.values, new MethodGen$2(this)); + this.update(); + } + + public Set createValues(Set values, Set values2) { + TreeSet treeSet = new TreeSet(); + Set values3 = values.size() < values2.size() ? values : values2; + Set values4 = values.size() < values2.size() ? values2 : values; + for (Object result : values3) { + if (values4.contains(result)) { + treeSet.add(result); + } + } + return treeSet; + } + + public void processValues(Set values, Set values3) { + Iterator iterator2 = values.iterator(); + label36: + while (true) { + for (Iterator iterator3 = iterator2; iterator3.hasNext(); iterator3 = iterator2) { + String text = (String) iterator2.next(); + if (!"-=404=-".equals(text)) { + ClassGen classGen; + if ((classGen = this.classStorage.getClassGen(text)) != null && classGen.isEnabled5()) { + Iterator iterator4; + iterator3 = + iterator4 = this.createValues(this.createValues(classGen), values3).iterator(); + while (iterator3.hasNext()) { + Set values4 = this.values2; + StringBuilder stringBuilder = + new StringBuilder().insert(0, classGen.getClassName()).append("&"); + iterator3 = iterator4; + values4.add(stringBuilder.append(iterator4.next()).toString()); + } + } + continue label36; + } + } + return; + } + } + + public Vector getValues() { + return this.values; + } + + public void processClassGen3(ClassGen classGen) { + this.processClassGen(classGen.getSuperclassName(), classGen); + int value; + String[] texts; + for (int value2 = value = (texts = classGen.getInterfaceNames()).length - 1; + value2 >= 0; + value2 = value) { + int value3 = value; + String[] texts2 = texts; + value--; + this.processClassGen(texts2[value3], classGen); + } + } + + public Set createValues(ClassGen classGen) { + TreeSet treeSet = new TreeSet(); + com.allatori.lib.bcel.classfile.Method[] methods; + int value; + for (int value2 = value = (methods = classGen.getMethods()).length - 1; + value2 >= 0; + value2 = --value) { + com.allatori.lib.bcel.classfile.Method method = methods[value]; + if (this.matchesMethod(method)) { + treeSet.add(method.getText() + "&" + method.getText2()); + } + } + return treeSet; + } + + public ClassHierarchy(ClassStorage classStorage2) { + super(); + this.entries2 = new Hashtable(); + this.values2 = new TreeSet(); + this.entries = new Hashtable(); + this.classStorage = classStorage2; + } + + public void processText(Set values, String text) { + values.add(text); + ClassGen classGen = this.classStorage.getClassGen(text); + if (classGen != null) { + this.processText(values, classGen.getSuperclassName()); + int value; + String[] texts; + for (int value2 = value = (texts = classGen.getInterfaceNames()).length - 1; + value2 >= 0; + value2 = value) { + int value3 = value; + String[] texts2 = texts; + value--; + this.processText(values, texts2[value3]); + } + } else { + try { + Class classValue; + if ((classValue = Class.forName(text, false, this.classStorage.getClassLoader())) + .getSuperclass() + != null) { + this.processText(values, classValue.getSuperclass().getName()); + } + Class[] classs; + int value4 = (classs = classValue.getInterfaces()).length - 1; + while (value4 >= 0) { + int value5 = value4; + Class[] classs2 = classs; + value4--; + this.processText(values, classs2[value5].getName()); + } + } catch (Exception exception) { + values.add("-=404=-"); + if (!this.entries.containsKey(text)) { + this.entries.put(text, ""); + Log.warn("Class '" + text + "' cannot be found."); + } + } + } + } + + public boolean matchesMethod(com.allatori.lib.bcel.classfile.Method method) { + return !method.isEnabled9() && !method.isEnabled11(); + } + + public Vector getValues(String text) { + Vector vector; + return (vector = (Vector) this.entries2.get(text)) != null ? vector : VALUES; + } + + public Set createValues2(ClassGen classGen) { + TreeSet treeSet = new TreeSet(); + this.processText(treeSet, classGen.getClassName()); + return treeSet; + } + + public boolean matchesMethod(Method method) { + return !Modifier.isPrivate(method.getModifiers()) && !Modifier.isStatic(method.getModifiers()); + } + + public void update3() { + Iterator iterator; + Iterator iterator2 = iterator = this.classStorage.getClassesByName2(); + while (iterator2.hasNext()) { + ClassGen classGen = (ClassGen) iterator.next(); + iterator2 = iterator; + this.processClassGen3(classGen); + this.processClassGen2(classGen); + } + if (this.entries.size() > 0) { + Log.warn( + "Some classes weren't found. It may result in weaker obfuscation. Add needed jars to the" + + " 'classpath' element of the configuration file."); + } + this.update2(); + } + + public void processClassGen(String text, ClassGen classGen) { + if (this.classStorage.getClassGen(text) != null) { + Vector vector; + if ((vector = (Vector) this.entries2.get(text)) == null) { + vector = new Vector(); + } + vector.add(classGen); + this.entries2.put(text, vector); + } + } +} diff --git a/src/main/java/com/allatori/bytecode/ClassHierarchyComparator.java b/src/main/java/com/allatori/bytecode/ClassHierarchyComparator.java new file mode 100644 index 0000000..476cdbe --- /dev/null +++ b/src/main/java/com/allatori/bytecode/ClassHierarchyComparator.java @@ -0,0 +1,21 @@ +package com.allatori.bytecode; + +import com.allatori.lib.bcel.generic.ClassGen; +import java.util.Comparator; + +public class ClassHierarchyComparator implements Comparator { + + public final ClassHierarchy classHierarchy; + + @Override + public int compare(Object result, Object result2) { + String className = ((ClassGen) result).getClassName(); + String className2 = ((ClassGen) result2).getClassName(); + return className.compareTo(className2); + } + + public ClassHierarchyComparator(ClassHierarchy classHierarchy2) { + super(); + this.classHierarchy = classHierarchy2; + } +} diff --git a/src/main/java/com/allatori/bytecode/ConstantPoolEditor.java b/src/main/java/com/allatori/bytecode/ConstantPoolEditor.java new file mode 100644 index 0000000..dd01d05 --- /dev/null +++ b/src/main/java/com/allatori/bytecode/ConstantPoolEditor.java @@ -0,0 +1,1131 @@ +package com.allatori.bytecode; + +import com.allatori.config.Configuration; +import com.allatori.lib.bcel.classfile.AnnotationDefault; +import com.allatori.lib.bcel.classfile.Attribute; +import com.allatori.lib.bcel.classfile.BootstrapMethod; +import com.allatori.lib.bcel.classfile.BootstrapMethods; +import com.allatori.lib.bcel.classfile.Code; +import com.allatori.lib.bcel.classfile.CodeException; +import com.allatori.lib.bcel.classfile.Constant; +import com.allatori.lib.bcel.classfile.ConstantCP; +import com.allatori.lib.bcel.classfile.ConstantClass; +import com.allatori.lib.bcel.classfile.ConstantInvokeDynamic; +import com.allatori.lib.bcel.classfile.ConstantMethodHandle; +import com.allatori.lib.bcel.classfile.ConstantMethodType; +import com.allatori.lib.bcel.classfile.ConstantNameAndType; +import com.allatori.lib.bcel.classfile.ConstantPool; +import com.allatori.lib.bcel.classfile.ConstantString; +import com.allatori.lib.bcel.classfile.ConstantUtf8; +import com.allatori.lib.bcel.classfile.ConstantValue; +import com.allatori.lib.bcel.classfile.Deprecated; +import com.allatori.lib.bcel.classfile.ElementValue; +import com.allatori.lib.bcel.classfile.EnclosingMethod; +import com.allatori.lib.bcel.classfile.ExceptionTable; +import com.allatori.lib.bcel.classfile.Field; +import com.allatori.lib.bcel.classfile.InnerClass; +import com.allatori.lib.bcel.classfile.InnerClasses; +import com.allatori.lib.bcel.classfile.LineNumberTable; +import com.allatori.lib.bcel.classfile.LocalVariable; +import com.allatori.lib.bcel.classfile.LocalVariableTable; +import com.allatori.lib.bcel.classfile.Method; +import com.allatori.lib.bcel.classfile.MethodParameter; +import com.allatori.lib.bcel.classfile.MethodParameters; +import com.allatori.lib.bcel.classfile.NestHost; +import com.allatori.lib.bcel.classfile.NestMembers; +import com.allatori.lib.bcel.classfile.PMGClass; +import com.allatori.lib.bcel.classfile.RuntimeInvisibleAnnotations; +import com.allatori.lib.bcel.classfile.Signature; +import com.allatori.lib.bcel.classfile.SourceFile; +import com.allatori.lib.bcel.classfile.StackMap; +import com.allatori.lib.bcel.classfile.StackMapEntry; +import com.allatori.lib.bcel.classfile.StackMapTable; +import com.allatori.lib.bcel.classfile.StackMapTableEntry; +import com.allatori.lib.bcel.classfile.StackMapType; +import com.allatori.lib.bcel.classfile.Synthetic; +import com.allatori.lib.bcel.classfile.Unknown; +import com.allatori.lib.bcel.generic.AnnotationElementValueGen; +import com.allatori.lib.bcel.generic.AnnotationEntryGen; +import com.allatori.lib.bcel.generic.ArrayElementValueGen; +import com.allatori.lib.bcel.generic.CPInstruction; +import com.allatori.lib.bcel.generic.ClassElementValueGen; +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.lib.bcel.generic.ConstantPoolGen; +import com.allatori.lib.bcel.generic.ElementValueGen; +import com.allatori.lib.bcel.generic.ElementValuePairGen; +import com.allatori.lib.bcel.generic.EnumElementValueGen; +import com.allatori.lib.bcel.generic.FieldGen; +import com.allatori.lib.bcel.generic.FieldGenOrMethodGen; +import com.allatori.lib.bcel.generic.Instruction; +import com.allatori.lib.bcel.generic.InstructionHandle; +import com.allatori.lib.bcel.generic.InstructionList; +import com.allatori.lib.bcel.generic.MethodGen; +import com.allatori.lib.bcel.generic.SimpleElementValueGen; +import com.allatori.model.ClassStorage; +import java.util.Arrays; +import java.util.List; +import java.util.TreeSet; + +public class ConstantPoolEditor { + + public ClassGen classGen; + + public TreeSet treeSet; + + public int[] counts; + + public ClassStorage classStorage; + + public boolean matchesAnnotationEntryGen(AnnotationEntryGen annotationEntryGen) { + if (annotationEntryGen.getText2().startsWith("Lcom/allatori/annotations/")) { + this.treeSet.add(annotationEntryGen.getTypeIndex()); + return true; + } + String text; + if (Configuration.getPackageRenamingOptions().isEnabled() + && (text = annotationEntryGen.getText2()).length() > 2 + && text.charAt(0) == 'L' + && text.charAt(text.length() - 1) == ';') { + String text2 = text.substring(1, text.length() - 1).replace('/', '.'); + if (Configuration.getPackageRenamingOptions() + .matchesText(this.classStorage, this.classGen, text2)) { + this.treeSet.add(annotationEntryGen.getTypeIndex()); + return true; + } + String text3 = Configuration.getMappingOptions().lookupTable.getText(text2); + if (Configuration.getPackageRenamingOptions() + .matchesText(this.classStorage, this.classGen, text3)) { + this.treeSet.add(annotationEntryGen.getTypeIndex()); + return true; + } + } + return false; + } + + public void processValues(List values) { + if (values != null) { + int value; + for (int value2 = value = values.size() - 1; value2 >= 0; value2 = value) { + int value3 = value; + value--; + this.processAnnotationEntryGen((AnnotationEntryGen) values.get(value3)); + } + } + } + + public void processAnnotationEntryGens(AnnotationEntryGen[] annotationEntryGens) { + if (annotationEntryGens != null) { + int value; + for (int value2 = value = annotationEntryGens.length - 1; value2 >= 0; value2 = value) { + int value3 = value; + value--; + this.processAnnotationEntryGen(annotationEntryGens[value3]); + } + } + } + + public void processConstantPool(Attribute[] attributes, ConstantPool constantPool) { + int value; + for (int value2 = value = attributes.length - 1; value2 >= 0; value2 = --value) { + Attribute attribute; + Attribute attribute2 = attribute = attributes[value]; + attribute2.setConstantPool(constantPool); + if (!(attribute2 instanceof LocalVariableTable)) { + attribute.setName_index(this.counts[attribute.getName_index()]); + } + if (attribute instanceof Code) { + Code code = (Code) attribute; + this.processConstantPool(code.getAttributes(), constantPool); + CodeException[] codeExceptions; + int value3; + for (int value4 = value3 = (codeExceptions = code.getExceptionTable()).length - 1; + value4 >= 0; + value4 = --value3) { + int value5; + if ((value5 = codeExceptions[value3].getCatch_type()) != 0) { + codeExceptions[value3].setCatch_type(this.counts[value5]); + } + } + } else if (attribute instanceof ConstantValue) { + ConstantValue constantValue = (ConstantValue) attribute; + constantValue.setConstantValueIndex(this.counts[constantValue.getConstantValueIndex()]); + } else if (!(attribute instanceof Deprecated)) { + if (attribute instanceof ExceptionTable) { + ExceptionTable exceptionTable; + int[] values; + int value6; + for (int value7 = + value6 = + (values = + (exceptionTable = (ExceptionTable) attribute) + .getExceptionIndexTable()) + .length + - 1; + value7 >= 0; + value7 = value6) { + int value8 = this.counts[values[value6]]; + int value9 = value6; + int[] values2 = values; + value6--; + values2[value9] = value8; + } + exceptionTable.setExceptionIndexTable(values); + } else { + int value10; + if (attribute instanceof InnerClasses) { + InnerClass[] innerClasss; + for (int value11 = + value10 = + (innerClasss = ((InnerClasses) attribute).getInnerClasses()).length - 1; + value11 >= 0; + value11 = value10) { + innerClasss[value10].setInner_name_index( + this.counts[innerClasss[value10].getInner_name_index()]); + innerClasss[value10].setInner_class_index( + this.counts[innerClasss[value10].getInner_class_index()]); + InnerClass innerClass = innerClasss[value10]; + int[] values3 = this.counts; + int outer_class_index = innerClasss[value10].getOuter_class_index(); + value10--; + innerClass.setOuter_class_index(values3[outer_class_index]); + } + } else if (!(attribute instanceof LineNumberTable)) { + if (attribute instanceof LocalVariableTable) { + try { + LocalVariable[] localVariables; + int value12 = + (localVariables = ((LocalVariableTable) attribute).getLocalVariableTable()) + .length + - 1; + while (value12 >= 0) { + localVariables[value12].setName_index( + this.counts[localVariables[value12].getName_index()]); + LocalVariable localVariable = localVariables[value12]; + int[] values4 = this.counts; + int signature_index = localVariables[value12].getSignature_index(); + value12--; + localVariable.setSignature_index(values4[signature_index]); + } + } catch (ArrayIndexOutOfBoundsException arrayIndexOutOfBoundsException) { + } + } else if (attribute instanceof PMGClass) { + PMGClass pMGClass = (PMGClass) attribute; + pMGClass.setPmg_class_index(this.counts[pMGClass.getPmg_class_index()]); + pMGClass.setPmg_index(this.counts[pMGClass.getPmg_index()]); + } else if (attribute instanceof Signature) { + Signature signature = (Signature) attribute; + signature.setSignatureIndex(this.counts[signature.getSignatureIndex()]); + } else if (attribute instanceof SourceFile) { + SourceFile sourceFile = (SourceFile) attribute; + sourceFile.setSourceFileIndex(this.counts[sourceFile.getSourceFileIndex()]); + } else { + int value13; + if (attribute instanceof StackMap) { + StackMapEntry[] stackMapEntrys; + for (int value14 = + value13 = + (stackMapEntrys = ((StackMap) attribute).getStackMap()).length - 1; + value14 >= 0; + value14 = --value13) { + int value15; + StackMapType[] stackMapTypes; + StackMapEntry stackMapEntry; + for (int value16 = + value15 = + (stackMapTypes = + (stackMapEntry = stackMapEntrys[value13]) + .getTypes_of_locals()) + .length + - 1; + value16 >= 0; + value16 = --value15) { + StackMapType stackMapType; + if ((stackMapType = stackMapTypes[value15]).getType() == 7) { + stackMapType.setIndex(this.counts[stackMapType.getIndex()]); + } + } + StackMapType[] stackMapTypes2; + int value17; + for (int value18 = + value17 = + (stackMapTypes2 = stackMapEntry.getTypes_of_stack_items()).length - 1; + value18 >= 0; + value18 = --value17) { + StackMapType stackMapType2; + if ((stackMapType2 = stackMapTypes2[value17]).getType() == 7) { + stackMapType2.setIndex(this.counts[stackMapType2.getIndex()]); + } + } + } + } else if (!(attribute instanceof Synthetic)) { + if (attribute instanceof EnclosingMethod) { + EnclosingMethod enclosingMethod = (EnclosingMethod) attribute; + enclosingMethod.setClassIndex(this.counts[enclosingMethod.getClassIndex()]); + if (enclosingMethod.getMethodIndex() != 0) { + enclosingMethod.setMethodIndex(this.counts[enclosingMethod.getMethodIndex()]); + } + } else if (attribute instanceof AnnotationDefault) { + AnnotationDefault annotationDefault = (AnnotationDefault) attribute; + ElementValue defaultValue = ((AnnotationDefault) attribute).getDefaultValue(); + ElementValueGen elementValueGen = + ElementValueGen.copy(defaultValue, new ConstantPoolGen(constantPool), false); + this.processElementValueGen(elementValueGen); + annotationDefault.setDefaultValue(elementValueGen.getElementValue()); + } else if (attribute instanceof BootstrapMethods) { + BootstrapMethod[] bootstrapMethods; + int value19 = + (bootstrapMethods = ((BootstrapMethods) attribute).getBootstrapMethods()) + .length; + int value20; + for (int value21 = value20 = 0; value21 < value19; value21 = value20) { + BootstrapMethod bootstrapMethod = bootstrapMethods[value20]; + bootstrapMethod.setBootstrapMethodRef( + this.counts[bootstrapMethod.getBootstrap_method_ref()]); + int[] values5; + int value22; + for (int value23 = + value22 = + (values5 = new int[bootstrapMethod.getBootstrapArguments().length]) + .length + - 1; + value23 >= 0; + value23 = value22) { + int value24 = this.counts[bootstrapMethod.getBootstrapArguments()[value22]]; + int value25 = value22; + int[] values6 = values5; + value22--; + values6[value25] = value24; + } + value20++; + bootstrapMethod.setBootstrapArguments(values5); + } + } else if (!(attribute instanceof StackMapTable)) { + if (attribute instanceof NestHost) { + NestHost nestHost = (NestHost) attribute; + nestHost.setHostClassIndex(this.counts[nestHost.getHostClassIndex()]); + } else { + int value26; + if (attribute instanceof NestMembers) { + int[] values7; + for (int value27 = + value26 = + (values7 = ((NestMembers) attribute).getClasses()).length - 1; + value27 >= 0; + value27 = value26) { + int value28 = this.counts[values7[value26]]; + int value29 = value26; + int[] values8 = values7; + value26--; + values8[value29] = value28; + } + } else if (attribute instanceof MethodParameters) { + MethodParameter[] methodParameters; + int value30 = + (methodParameters = ((MethodParameters) attribute).getParameters()) + .length; + int value31; + for (int value32 = value31 = 0; value32 < value30; value32 = value31) { + MethodParameter methodParameter = methodParameters[value31]; + int[] values9 = this.counts; + int nameIndex = methodParameter.getNameIndex(); + value31++; + methodParameter.setNameIndex(values9[nameIndex]); + } + } else if (attribute instanceof Unknown) { + } + } + } else { + StackMapTableEntry[] stackMapTableEntrys; + int value33 = + (stackMapTableEntrys = ((StackMapTable) attribute).getStackMap()).length; + int value34; + for (int value35 = value34 = 0; value35 < value33; value35 = ++value34) { + StackMapTableEntry stackMapTableEntry; + if ((stackMapTableEntry = stackMapTableEntrys[value34]).getTypesOfLocals() + != null) { + StackMapType[] stackMapTypes3; + int value36 = (stackMapTypes3 = stackMapTableEntry.getTypesOfLocals()).length; + int value37; + for (int value38 = value37 = 0; value38 < value36; value38 = ++value37) { + StackMapType stackMapType3; + if ((stackMapType3 = stackMapTypes3[value37]).getType() == 7) { + stackMapType3.setIndex(this.counts[stackMapType3.getIndex()]); + } + } + } + if (stackMapTableEntry.getTypesOfStackItems() != null) { + StackMapType[] stackMapTypes4; + int value39 = + (stackMapTypes4 = stackMapTableEntry.getTypesOfStackItems()).length; + int value40; + for (int value41 = value40 = 0; value41 < value39; value41 = ++value40) { + StackMapType stackMapType4; + if ((stackMapType4 = stackMapTypes4[value40]).getType() == 7) { + stackMapType4.setIndex(this.counts[stackMapType4.getIndex()]); + } + } + } + } + } + } + } + } + } + } + } + } + + public void processConstantPoolGen( + AnnotationEntryGen[] annotationEntryGens, ConstantPoolGen constantPoolGen) { + if (annotationEntryGens != null) { + int value; + for (int value2 = value = annotationEntryGens.length - 1; value2 >= 0; value2 = value) { + int value3 = value; + value--; + this.processConstantPoolGen(annotationEntryGens[value3], constantPoolGen); + } + } + } + + public void processMethodGen(MethodGen methodGen) { + InstructionList instructionList; + if ((instructionList = methodGen.getInstructionList()) != null) { + int value; + InstructionHandle[] instructionHandles; + for (int value2 = + value = (instructionHandles = instructionList.getInstructionHandles()).length - 1; + value2 >= 0; + value2 = --value) { + Instruction instruction; + if ((instruction = instructionHandles[value].getInstruction()) instanceof CPInstruction) { + CPInstruction cPInstruction = (CPInstruction) instruction; + cPInstruction.setIndex(this.counts[cPInstruction.getIndex()]); + } + } + } + } + + public void processElementValueGen(ElementValueGen elementValueGen) { + if (elementValueGen instanceof AnnotationElementValueGen) { + this.processAnnotationEntryGen(((AnnotationElementValueGen) elementValueGen).getAnnotation()); + } else { + int value; + if (elementValueGen instanceof ArrayElementValueGen) { + List values; + for (int value2 = + value = + (values = ((ArrayElementValueGen) elementValueGen).getElementValues()).size() + - 1; + value2 >= 0; + value2 = value) { + int value3 = value; + List values2 = values; + value--; + this.processElementValueGen((ElementValueGen) values2.get(value3)); + } + } else { + if (elementValueGen instanceof ClassElementValueGen) { + ClassElementValueGen classElementValueGen = (ClassElementValueGen) elementValueGen; + classElementValueGen.setIdx(this.counts[classElementValueGen.getIndex()]); + return; + } + if (elementValueGen instanceof EnumElementValueGen) { + EnumElementValueGen enumElementValueGen = (EnumElementValueGen) elementValueGen; + enumElementValueGen.setTypeIdx(this.counts[enumElementValueGen.getTypeIdx()]); + enumElementValueGen.setValueIdx(this.counts[enumElementValueGen.getValueIdx()]); + return; + } + if (elementValueGen instanceof SimpleElementValueGen) { + SimpleElementValueGen simpleElementValueGen = (SimpleElementValueGen) elementValueGen; + simpleElementValueGen.setIdx(this.counts[simpleElementValueGen.getIndex()]); + } + } + } + } + + public void processClassGen(ClassGen classGen2) { + ClassGen classGen3 = this.classGen = classGen2; + this.treeSet.clear(); + this.processClassGen2(classGen3); + this.processClassGen3(classGen2); + } + + public ConstantPoolEditor(ClassStorage classStorage2) { + super(); + this.treeSet = new TreeSet(); + this.classStorage = classStorage2; + } + + public void processConstantPoolGen(MethodGen methodGen, ConstantPoolGen constantPoolGen) { + InstructionList instructionList; + if ((instructionList = methodGen.getInstructionList()) != null) { + int value; + InstructionHandle[] instructionHandles; + for (int value2 = + value = (instructionHandles = instructionList.getInstructionHandles()).length - 1; + value2 >= 0; + value2 = --value) { + Instruction instruction; + if ((instruction = instructionHandles[value].getInstruction()) instanceof CPInstruction) { + CPInstruction cPInstruction = (CPInstruction) instruction; + this.processConstantPoolGen(cPInstruction.getIndex(), constantPoolGen); + } + } + } + } + + public void processFieldGen(ClassGen classGen, MethodGen methodGen, FieldGen fieldGen) { + Attribute[] attributes = null; + if (classGen != null) { + attributes = classGen.getAttributes(); + } + if (methodGen != null) { + attributes = methodGen.getAttributes(); + } + if (fieldGen != null) { + attributes = fieldGen.getAttributes(); + } + int value; + if (methodGen != null) { + Attribute[] attributes2; + for (int value2 = value = (attributes2 = methodGen.getCodeAttributes()).length - 1; + value2 >= 0; + value2 = --value) { + if (attributes2[value] instanceof Unknown) { + methodGen.removeCodeAttribute(attributes2[value]); + } + } + } + if (attributes != null) { + int value3; + for (int value4 = value3 = attributes.length - 1; value4 >= 0; value4 = --value3) { + if (attributes[value3] instanceof Unknown) { + if (classGen != null) { + classGen.processAttribute2(attributes[value3]); + } + if (methodGen != null) { + methodGen.removeAttribute(attributes[value3]); + } + if (fieldGen != null) { + fieldGen.removeAttribute(attributes[value3]); + } + } + } + } + } + + public void processConstantPoolGen(List values, ConstantPoolGen constantPoolGen) { + if (values != null) { + int value; + for (int value2 = value = values.size() - 1; value2 >= 0; value2 = value) { + Object result = values.get(value); + value--; + this.processConstantPoolGen((AnnotationEntryGen) result, constantPoolGen); + } + } + } + + public void processConstantPoolGen( + AnnotationEntryGen annotationEntryGen, ConstantPoolGen constantPoolGen) { + if (!this.matchesAnnotationEntryGen(annotationEntryGen)) { + this.processConstantPoolGen(annotationEntryGen.getTypeIndex(), constantPoolGen); + int value; + List values; + for (int value2 = value = (values = annotationEntryGen.getValues()).size() - 1; + value2 >= 0; + value2 = value) { + ElementValuePairGen elementValuePairGen; + ElementValuePairGen elementValuePairGen2 = + elementValuePairGen = (ElementValuePairGen) values.get(value); + this.processConstantPoolGen(elementValuePairGen.getNameIndex(), constantPoolGen); + value--; + this.processConstantPoolGen(elementValuePairGen2.getValue(), constantPoolGen); + } + } + } + + public void processEnabled( + Attribute[] attributes, ConstantPoolGen constantPoolGen, boolean matches, boolean matches2) { + int value; + for (int value2 = value = attributes.length - 1; value2 >= 0; value2 = --value) { + Attribute attribute; + Attribute attribute2 = attribute = attributes[value]; + attribute2.setConstantPool(constantPoolGen.getConstantPool()); + if (!(attribute2 instanceof Unknown) + && !(attribute instanceof RuntimeInvisibleAnnotations) + && (!matches || !(attribute instanceof Signature)) + && (!matches2 + || !(attribute instanceof InnerClasses) && !(attribute instanceof EnclosingMethod))) { + this.processConstantPoolGen(attribute.getName_index(), constantPoolGen); + } + if (attribute instanceof Code) { + Code code = (Code) attribute; + this.processEnabled(code.getAttributes(), constantPoolGen, matches, matches2); + CodeException[] codeExceptions; + int value3; + for (int value4 = value3 = (codeExceptions = code.getExceptionTable()).length - 1; + value4 >= 0; + value4 = value3) { + CodeException codeException = codeExceptions[value3]; + value3--; + this.processConstantPoolGen(codeException.getCatch_type(), constantPoolGen); + } + } else if (attribute instanceof ConstantValue) { + ConstantValue constantValue = (ConstantValue) attribute; + this.processConstantPoolGen(constantValue.getConstantValueIndex(), constantPoolGen); + } else if (!(attribute instanceof Deprecated)) { + int value5; + if (attribute instanceof ExceptionTable) { + int[] values; + for (int value6 = + value5 = + (values = ((ExceptionTable) attribute).getExceptionIndexTable()).length - 1; + value6 >= 0; + value6 = value5) { + int value7 = value5; + int[] values2 = values; + value5--; + this.processConstantPoolGen(values2[value7], constantPoolGen); + } + } else if (attribute instanceof InnerClasses) { + int value8; + if (!matches2) { + InnerClass[] innerClasss; + for (int value9 = + value8 = + (innerClasss = ((InnerClasses) attribute).getInnerClasses()).length - 1; + value9 >= 0; + value9 = value8) { + this.processConstantPoolGen( + innerClasss[value8].getInner_name_index(), constantPoolGen); + this.processConstantPoolGen( + innerClasss[value8].getInner_class_index(), constantPoolGen); + InnerClass innerClass = innerClasss[value8]; + value8--; + this.processConstantPoolGen(innerClass.getOuter_class_index(), constantPoolGen); + } + } + } else if (!(attribute instanceof LineNumberTable)) { + int value10; + if (attribute instanceof LocalVariableTable) { + LocalVariable[] localVariables; + for (int value11 = + value10 = + (localVariables = ((LocalVariableTable) attribute).getLocalVariableTable()) + .length + - 1; + value11 >= 0; + value11 = value10) { + this.processConstantPoolGen(localVariables[value10].getName_index(), constantPoolGen); + LocalVariable localVariable = localVariables[value10]; + value10--; + this.processConstantPoolGen(localVariable.getSignature_index(), constantPoolGen); + } + } else if (attribute instanceof PMGClass) { + PMGClass pMGClass; + PMGClass pMGClass2 = pMGClass = (PMGClass) attribute; + this.processConstantPoolGen(pMGClass.getPmg_class_index(), constantPoolGen); + this.processConstantPoolGen(pMGClass2.getPmg_index(), constantPoolGen); + } else if (attribute instanceof Signature) { + if (!matches) { + Signature signature = (Signature) attribute; + this.processConstantPoolGen(signature.getSignatureIndex(), constantPoolGen); + } + } else if (attribute instanceof SourceFile) { + SourceFile sourceFile = (SourceFile) attribute; + this.processConstantPoolGen(sourceFile.getSourceFileIndex(), constantPoolGen); + } else { + int value12; + if (attribute instanceof StackMap) { + StackMapEntry[] stackMapEntrys; + for (int value13 = + value12 = (stackMapEntrys = ((StackMap) attribute).getStackMap()).length - 1; + value13 >= 0; + value13 = --value12) { + StackMapEntry stackMapEntry; + StackMapType[] stackMapTypes; + int value14; + for (int value15 = + value14 = + (stackMapTypes = + (stackMapEntry = stackMapEntrys[value12]) + .getTypes_of_locals()) + .length + - 1; + value15 >= 0; + value15 = --value14) { + StackMapType stackMapType; + if ((stackMapType = stackMapTypes[value14]).getType() == 7) { + this.processConstantPoolGen(stackMapType.getIndex(), constantPoolGen); + } + } + StackMapType[] stackMapTypes2; + int value16; + for (int value17 = + value16 = + (stackMapTypes2 = stackMapEntry.getTypes_of_stack_items()).length - 1; + value17 >= 0; + value17 = --value16) { + StackMapType stackMapType2; + if ((stackMapType2 = stackMapTypes2[value16]).getType() == 7) { + this.processConstantPoolGen(stackMapType2.getIndex(), constantPoolGen); + } + } + } + } else if (!(attribute instanceof Synthetic)) { + if (attribute instanceof EnclosingMethod) { + if (!matches2) { + EnclosingMethod enclosingMethod = (EnclosingMethod) attribute; + this.processConstantPoolGen(enclosingMethod.getClassIndex(), constantPoolGen); + if (enclosingMethod.getMethodIndex() != 0) { + this.processConstantPoolGen(enclosingMethod.getMethodIndex(), constantPoolGen); + } + } + } else if (attribute instanceof AnnotationDefault) { + ElementValueGen elementValueGen = + ElementValueGen.copy( + ((AnnotationDefault) attribute).getDefaultValue(), constantPoolGen, false); + this.processConstantPoolGen(elementValueGen, constantPoolGen); + } else if (attribute instanceof BootstrapMethods) { + BootstrapMethod[] bootstrapMethods; + int value18 = + (bootstrapMethods = ((BootstrapMethods) attribute).getBootstrapMethods()) + .length; + int value19; + for (int value20 = value19 = 0; value20 < value18; value20 = ++value19) { + BootstrapMethod bootstrapMethod = bootstrapMethods[value19]; + this.processConstantPoolGen( + bootstrapMethod.getBootstrap_method_ref(), constantPoolGen); + int[] values3; + int value21 = (values3 = bootstrapMethod.getBootstrapArguments()).length; + int value22; + for (int value23 = value22 = 0; value23 < value21; value23 = value22) { + int value24; + int value25 = value24 = values3[value22]; + value22++; + this.processConstantPoolGen(value25, constantPoolGen); + } + } + } else if (!(attribute instanceof StackMapTable)) { + if (attribute instanceof NestHost) { + NestHost nestHost = (NestHost) attribute; + this.processConstantPoolGen(nestHost.getHostClassIndex(), constantPoolGen); + } else { + int value26; + if (attribute instanceof NestMembers) { + int[] values4; + for (int value27 = + value26 = (values4 = ((NestMembers) attribute).getClasses()).length - 1; + value27 >= 0; + value27 = value26) { + int value28 = value26; + int[] values5 = values4; + value26--; + this.processConstantPoolGen(values5[value28], constantPoolGen); + } + } else if (attribute instanceof MethodParameters) { + MethodParameter[] methodParameters; + int value29 = + (methodParameters = ((MethodParameters) attribute).getParameters()).length; + int value30; + for (int value31 = value30 = 0; value31 < value29; value31 = value30) { + MethodParameter methodParameter = methodParameters[value30]; + value30++; + this.processConstantPoolGen(methodParameter.getNameIndex(), constantPoolGen); + } + } else if (attribute instanceof Unknown) { + } + } + } else { + StackMapTableEntry[] stackMapTableEntrys; + int value32 = + (stackMapTableEntrys = ((StackMapTable) attribute).getStackMap()).length; + int value33; + for (int value34 = value33 = 0; value34 < value32; value34 = ++value33) { + StackMapTableEntry stackMapTableEntry; + if ((stackMapTableEntry = stackMapTableEntrys[value33]).getTypesOfLocals() + != null) { + StackMapType[] stackMapTypes3; + int value35 = (stackMapTypes3 = stackMapTableEntry.getTypesOfLocals()).length; + int value36; + for (int value37 = value36 = 0; value37 < value35; value37 = ++value36) { + StackMapType stackMapType3; + if ((stackMapType3 = stackMapTypes3[value36]).getType() == 7) { + this.processConstantPoolGen(stackMapType3.getIndex(), constantPoolGen); + } + } + } + if (stackMapTableEntry.getTypesOfStackItems() != null) { + StackMapType[] stackMapTypes4; + int value38 = + (stackMapTypes4 = stackMapTableEntry.getTypesOfStackItems()).length; + int value39; + for (int value40 = value39 = 0; value40 < value38; value40 = ++value39) { + StackMapType stackMapType4; + if ((stackMapType4 = stackMapTypes4[value39]).getType() == 7) { + this.processConstantPoolGen(stackMapType4.getIndex(), constantPoolGen); + } + } + } + } + } + } + } + } + } + } + } + + public void processConstantPoolGen( + ElementValueGen elementValueGen, ConstantPoolGen constantPoolGen) { + if (elementValueGen instanceof AnnotationElementValueGen) { + this.processConstantPoolGen( + ((AnnotationElementValueGen) elementValueGen).getAnnotation(), constantPoolGen); + } else { + int value; + if (elementValueGen instanceof ArrayElementValueGen) { + List values; + for (int value2 = + value = + (values = ((ArrayElementValueGen) elementValueGen).getElementValues()).size() + - 1; + value2 >= 0; + value2 = value) { + Object result = values.get(value); + value--; + this.processConstantPoolGen((ElementValueGen) result, constantPoolGen); + } + } else { + if (elementValueGen instanceof ClassElementValueGen) { + this.processConstantPoolGen( + ((ClassElementValueGen) elementValueGen).getIndex(), constantPoolGen); + return; + } + if (elementValueGen instanceof EnumElementValueGen) { + this.processConstantPoolGen( + ((EnumElementValueGen) elementValueGen).getTypeIdx(), constantPoolGen); + this.processConstantPoolGen( + ((EnumElementValueGen) elementValueGen).getValueIdx(), constantPoolGen); + return; + } + if (elementValueGen instanceof SimpleElementValueGen) { + this.processConstantPoolGen( + ((SimpleElementValueGen) elementValueGen).getIndex(), constantPoolGen); + } + } + } + } + + public void processConstantPoolGen(int value, ConstantPoolGen constantPoolGen) { + if (value != -1) { + this.counts[value] = 1; + Constant constant; + if ((constant = constantPoolGen.getConstant(value)) != null) { + int size = constantPoolGen.getSize(); + int value2; + for (int value3 = value2 = value + 1; + value3 < size && constantPoolGen.getConstant(value2) == null; + value3 = value2) { + byte value4 = 1; + int value5 = value2; + int[] values = this.counts; + value2++; + values[value5] = value4; + } + } + if (constant instanceof ConstantClass) { + ConstantClass constantClass = (ConstantClass) constant; + this.processConstantPoolGen(constantClass.getNameIndex(), constantPoolGen); + } else if (constant instanceof ConstantCP) { + ConstantCP constantCP; + ConstantCP constantCP2 = constantCP = (ConstantCP) constant; + this.processConstantPoolGen(constantCP.getClass_index(), constantPoolGen); + this.processConstantPoolGen(constantCP2.getName_and_type_index(), constantPoolGen); + } else if (constant instanceof ConstantNameAndType) { + ConstantNameAndType constantNameAndType; + ConstantNameAndType constantNameAndType2 = + constantNameAndType = (ConstantNameAndType) constant; + this.processConstantPoolGen(constantNameAndType.getName_index(), constantPoolGen); + this.processConstantPoolGen(constantNameAndType2.getSignature_index(), constantPoolGen); + } else if (constant instanceof ConstantString) { + ConstantString constantString = (ConstantString) constant; + this.processConstantPoolGen(constantString.getStringIndex(), constantPoolGen); + } else if (constant instanceof ConstantInvokeDynamic) { + ConstantInvokeDynamic constantInvokeDynamic = (ConstantInvokeDynamic) constant; + this.processConstantPoolGen( + constantInvokeDynamic.getBootstrapMethodAttrIndex2(), constantPoolGen); + } else if (constant instanceof ConstantMethodHandle) { + ConstantMethodHandle constantMethodHandle = (ConstantMethodHandle) constant; + this.processConstantPoolGen(constantMethodHandle.getReference_index(), constantPoolGen); + } else { + if (constant instanceof ConstantMethodType) { + ConstantMethodType constantMethodType = (ConstantMethodType) constant; + this.processConstantPoolGen(constantMethodType.getDescriptorIndex(), constantPoolGen); + } + } + } + } + + public void processAnnotationEntryGen(AnnotationEntryGen annotationEntryGen) { + annotationEntryGen.setTypeIndex(this.counts[annotationEntryGen.getTypeIndex()]); + int value; + List values; + for (int value2 = value = (values = annotationEntryGen.getValues()).size() - 1; + value2 >= 0; + value2 = value) { + ElementValuePairGen elementValuePairGen; + ElementValuePairGen elementValuePairGen2 = + elementValuePairGen = (ElementValuePairGen) values.get(value); + int value3 = this.counts[elementValuePairGen.getNameIndex()]; + value--; + elementValuePairGen2.setNameIdx(value3); + this.processElementValueGen(elementValuePairGen2.getValue()); + } + } + + public void processClassGen2(ClassGen classGen) { + ConstantPoolGen constantPool = classGen.getConstantPool(); + int size = constantPool.getSize(); + this.counts = new int[size]; + Arrays.fill(this.counts, 0); + this.processConstantPoolGen(0, constantPool); + this.processConstantPoolGen(classGen.getClassNameIndex(), constantPool); + this.processConstantPoolGen(classGen.getSuperclassNameIndex(), constantPool); + int value; + int[] values; + for (int value2 = value = (values = classGen.getInterfaces()).length - 1; + value2 >= 0; + value2 = value) { + int value3 = value; + int[] values2 = values; + value--; + this.processConstantPoolGen(values2[value3], constantPool); + } + this.processEnabled(classGen.getAttributes(), constantPool, false, false); + this.processConstantPoolGen(classGen.getAnnotationEntries(), constantPool); + int value4; + Method[] methods; + for (int value5 = value4 = (methods = classGen.getMethods()).length - 1; + value5 >= 0; + value5 = --value4) { + Method method; + Method method2 = method = methods[value4]; + this.processConstantPoolGen(method.getCount3(), constantPool); + this.processConstantPoolGen(method.getCount(), constantPool); + this.processEnabled(method.getAttributes(), constantPool, false, false); + MethodGen methodGen; + this.processConstantPoolGen( + methodGen = + MethodFactory.createMethodGen( + method2, classGen.getClassName(), constantPool, constantPool.getConstantPool()), + constantPool); + this.processConstantPoolGen(methodGen.getAnnotationEntryGens(), constantPool); + int value6; + for (int value7 = value6 = methodGen.getArgumentTypes().length - 1; + value7 >= 0; + value7 = value6) { + int value8 = value6; + MethodGen methodGen2 = methodGen; + value6--; + this.processConstantPoolGen(methodGen2.getAnnotationsOnParameter(value8), constantPool); + } + } + int value9; + Field[] fields; + for (int value10 = value9 = (fields = classGen.getFields()).length - 1; + value10 >= 0; + value10 = value9) { + Field field; + Field field2 = field = fields[value9]; + this.processConstantPoolGen(field.getCount3(), constantPool); + this.processConstantPoolGen(field.getCount(), constantPool); + this.processEnabled(field2.getAttributes(), constantPool, false, false); + FieldGen fieldGen = new FieldGen(field, constantPool); + value9--; + this.processConstantPoolGen(fieldGen.getAnnotationEntryGens(), constantPool); + } + int value11; + for (int value12 = value11 = constantPool.getSize() - 1; value12 >= 0; value12 = --value11) { + Constant constant; + if ((constant = constantPool.getConstant(value11)) instanceof ConstantUtf8) { + ConstantUtf8 constantUtf8 = (ConstantUtf8) constant; + if ("".equals(constantUtf8.getBytes())) { + this.processConstantPoolGen(value11, constantPool); + } + } + } + } + + public void processFieldGenOrMethodGen( + ClassGen classGen, FieldGenOrMethodGen fieldGenOrMethodGen) { + AnnotationEntryGen[] annotationEntryGens = null; + if (classGen != null) { + annotationEntryGens = classGen.getAnnotationEntries(); + } + if (fieldGenOrMethodGen != null) { + annotationEntryGens = fieldGenOrMethodGen.getAnnotationEntryGens(); + } + int value; + for (int value2 = value = 0; value2 < annotationEntryGens.length; value2 = ++value) { + AnnotationEntryGen annotationEntryGen = annotationEntryGens[value]; + if (this.treeSet.contains(annotationEntryGen.getTypeIndex())) { + if (classGen != null) { + classGen.addAnnotationEntry2(annotationEntryGen); + } + if (fieldGenOrMethodGen != null) { + fieldGenOrMethodGen.processAnnotationEntryGen2(annotationEntryGen); + } + } + } + } + + public void processClassGen3(ClassGen classGen) { + ConstantPoolGen constantPool = classGen.getConstantPool(); + int size = constantPool.getSize(); + int value = 0; + int value2; + for (int value3 = value2 = this.counts.length - 1; value3 >= 0; value3 = value2) { + int value4 = value2; + int[] values = this.counts; + int value5 = value; + value2--; + value = value5 + values[value4]; + } + Constant[] constants = new Constant[value]; + int value6 = 0; + int value7; + for (int value8 = value7 = 0; value8 < size; value8 = ++value7) { + Constant constant = constantPool.getConstant(value7); + if (this.counts[value7] == 1) { + if (constant != null) { + constant = constant.copy(); + } + constants[value6] = constant; + this.counts[value7] = value6++; + } + } + int value9; + for (int value10 = value9 = 0; value10 < value; value10 = ++value9) { + Constant constant2; + if ((constant2 = constants[value9]) instanceof ConstantClass) { + ConstantClass constantClass = (ConstantClass) constant2; + constantClass.setNameIndex(this.counts[constantClass.getNameIndex()]); + } else if (constant2 instanceof ConstantCP) { + ConstantCP constantCP = (ConstantCP) constant2; + constantCP.setClass_index(this.counts[constantCP.getClass_index()]); + constantCP.setName_and_type_index(this.counts[constantCP.getName_and_type_index()]); + } else if (constant2 instanceof ConstantNameAndType) { + ConstantNameAndType constantNameAndType = (ConstantNameAndType) constant2; + constantNameAndType.setName_index(this.counts[constantNameAndType.getName_index()]); + constantNameAndType.setSignature_index( + this.counts[constantNameAndType.getSignature_index()]); + } else if (constant2 instanceof ConstantString) { + ConstantString constantString = (ConstantString) constant2; + constantString.setStringIndex(this.counts[constantString.getStringIndex()]); + } else if (constant2 instanceof ConstantInvokeDynamic) { + ConstantInvokeDynamic constantInvokeDynamic = (ConstantInvokeDynamic) constant2; + constantInvokeDynamic.setCount2( + this.counts[constantInvokeDynamic.getBootstrapMethodAttrIndex2()]); + } else if (constant2 instanceof ConstantMethodHandle) { + ConstantMethodHandle constantMethodHandle = (ConstantMethodHandle) constant2; + constantMethodHandle.setReference_index( + this.counts[constantMethodHandle.getReference_index()]); + } else if (constant2 instanceof ConstantMethodType) { + ConstantMethodType constantMethodType = (ConstantMethodType) constant2; + constantMethodType.setDescriptorIndex(this.counts[constantMethodType.getDescriptorIndex()]); + } + } + ConstantPoolGen constantPoolGen; + ConstantPool constantPool2 = + (constantPoolGen = new ConstantPoolGen(constants)).getConstantPool(); + classGen.setConstantPool(constantPoolGen); + classGen.processCount2(this.counts[classGen.getClassNameIndex()]); + classGen.processCount3(this.counts[classGen.getSuperclassNameIndex()]); + Attribute[] attributes; + int value11 = (attributes = classGen.getAttributes()).length; + int value12; + for (int value13 = value12 = 0; value13 < value11; value13 = value12) { + int value14 = value12; + Attribute[] attributes2 = attributes; + value12++; + classGen.processAttribute2(attributes2[value14]); + } + this.processConstantPool(attributes, constantPool2); + int value15; + for (int value16 = value15 = 0; value16 < value11; value16 = value15) { + int value17 = value15; + Attribute[] attributes3 = attributes; + value15++; + classGen.processAttribute(attributes3[value17]); + } + this.processFieldGen(classGen, null, null); + this.processFieldGenOrMethodGen(classGen, null); + this.processAnnotationEntryGens(classGen.getAnnotationEntries()); + Method[] methods; + int value18; + for (int value19 = value18 = (methods = classGen.getMethods()).length - 1; + value19 >= 0; + value19 = value18) { + Method method; + int value20 = (method = methods[value18]).getLocalVariableTable() == null ? 1 : 0; + MethodGen methodGen = + MethodFactory.createMethodGen( + method, classGen.getClassName(), constantPoolGen, constantPool.getConstantPool()); + this.processMethodGen(methodGen); + this.processConstantPool(methodGen.getAttributes(), constantPool2); + this.processConstantPool( + new Attribute[] {methodGen.getLocalVariableTable(constantPoolGen)}, constantPool2); + this.processConstantPool(methodGen.getCodeAttributes(), constantPool2); + this.processFieldGen(null, methodGen, null); + this.processFieldGenOrMethodGen(null, methodGen); + this.processAnnotationEntryGens(methodGen.getAnnotationEntryGens()); + int value21; + for (int value22 = value21 = methodGen.getArgumentTypes().length - 1; + value22 >= 0; + value22 = value21) { + int value23 = value21; + value21--; + this.processValues(methodGen.getAnnotationsOnParameter(value23)); + } + label84: + { + if (value20 == 0) { + value19 = + Configuration.getRenamingOptions() + .getLocalVariableOptions() + .calculateCount(this.classStorage, classGen, methodGen); + Configuration.getRenamingOptions().getLocalVariableOptions(); + if (value19 != 4) { + break label84; + } + } + methodGen.getVariable_vec(); + } + Method method2 = methodGen.getMethod(); + method2.setCount3(this.counts[method.getCount3()]); + method2.setCount(this.counts[method.getCount()]); + int value24 = value18; + value18--; + classGen.setMethodAt(method2, value24); + } + Field[] fields; + int value25; + for (int value26 = value25 = (fields = classGen.getFields()).length - 1; + value26 >= 0; + value26 = value25) { + Field field = fields[value25]; + FieldGen fieldGen = new FieldGen(field, constantPool); + fieldGen.setConstantPool(constantPoolGen); + this.processConstantPool(fieldGen.getAttributes(), constantPool2); + this.processFieldGen(null, null, fieldGen); + this.processFieldGenOrMethodGen(null, fieldGen); + this.processAnnotationEntryGens(fieldGen.getAnnotationEntryGens()); + Field field2 = fieldGen.getField(); + field2.setCount3(this.counts[field.getCount3()]); + int value27 = this.counts[field.getCount()]; + value25--; + field2.setCount(value27); + classGen.replaceField(field, field2); + } + } +} diff --git a/src/main/java/com/allatori/bytecode/MethodFactory.java b/src/main/java/com/allatori/bytecode/MethodFactory.java new file mode 100644 index 0000000..7e06871 --- /dev/null +++ b/src/main/java/com/allatori/bytecode/MethodFactory.java @@ -0,0 +1,15 @@ +package com.allatori.bytecode; + +import com.allatori.lib.bcel.classfile.ConstantPool; +import com.allatori.lib.bcel.classfile.Method; +import com.allatori.lib.bcel.generic.ConstantPoolGen; +import com.allatori.lib.bcel.generic.MethodGen; + +public class MethodFactory { + + public static MethodGen createMethodGen( + Method method, String text, ConstantPoolGen constantPoolGen, ConstantPool constantPool) { + method.setConstantPool(constantPool); + return new MethodGen(method, text, constantPoolGen); + } +} diff --git a/src/main/java/com/allatori/bytecode/OrderedClassSet.java b/src/main/java/com/allatori/bytecode/OrderedClassSet.java new file mode 100644 index 0000000..b7e7a7d --- /dev/null +++ b/src/main/java/com/allatori/bytecode/OrderedClassSet.java @@ -0,0 +1,16 @@ +package com.allatori.bytecode; + +import java.util.TreeSet; + +public class OrderedClassSet extends TreeSet { + + @Override + public boolean contains(Object result) { + return true; + } + + @Override + public int size() { + return Integer.MAX_VALUE; + } +} diff --git a/src/main/java/com/allatori/cli/ObfuscationCommandSupport.java b/src/main/java/com/allatori/cli/ObfuscationCommandSupport.java new file mode 100644 index 0000000..5d22f66 --- /dev/null +++ b/src/main/java/com/allatori/cli/ObfuscationCommandSupport.java @@ -0,0 +1,236 @@ +package com.allatori.cli; + +import com.allatori.VersionInfo; +import com.allatori.config.ClassPathEntry; +import com.allatori.config.Configuration; +import com.allatori.config.ConfigurationException; +import com.allatori.config.InputEntry; +import com.allatori.config.InputJar; +import com.allatori.engine.ObfuscationException; +import com.allatori.io.ClassStorageClassLoader; +import com.allatori.io.DirectoryClassReader; +import com.allatori.io.DirectoryWriter; +import com.allatori.io.JarClassReader; +import com.allatori.io.JarWriter; +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.model.ClassStorage; +import com.allatori.util.Log; +import com.allatori.watermark.WatermarkProcessor; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.net.URL; +import java.util.Iterator; +import java.util.Vector; + +public class ObfuscationCommandSupport { + + public static void limitClassVersion(ClassStorage classStorage) { + Iterator classesByName2 = classStorage.getClassesByName2(); + while (classesByName2.hasNext()) { + ClassGen classGen; + if ((classGen = (ClassGen) classesByName2.next()).getMajor() > 50) { + classGen.setMajor(50); + } + } + } + + public static void writeOutputs(ClassStorage classStorage) + throws IOException, FileNotFoundException { + JarWriter jarWriter = new JarWriter(); + Iterator iterator2; + Iterator iterator3 = iterator2 = Configuration.getInputOptions().getValues().iterator(); + while (iterator3.hasNext()) { + InputJar inputJar = (InputJar) iterator2.next(); + iterator3 = iterator2; + jarWriter.processClassStorage(inputJar.text2, inputJar.text, classStorage); + } + Iterator iterator4; + iterator3 = iterator4 = Configuration.getInputOptions().getValues3().iterator(); + while (iterator3.hasNext()) { + InputEntry inputEntry = (InputEntry) iterator4.next(); + iterator3 = iterator4; + jarWriter.processClassStorage(inputEntry.text2, inputEntry.text, classStorage); + } + if (Configuration.getInputOptions().getText() != null) { + Vector vector; + String[] texts = new String[(vector = Configuration.getInputOptions().getValues3()).size()]; + int value; + for (int value2 = value = 0; value2 < vector.size(); value2 = value) { + String text3 = ((InputEntry) vector.get(value)).text; + int value3 = value; + value++; + texts[value3] = text3; + } + jarWriter.processText(texts, Configuration.getInputOptions().getText()); + } + jarWriter.update(); + } + + public static void loadConfiguration(String text) throws Exception { + try { + Configuration.processText(text); + } catch (ConfigurationException configurationException) { + if (configurationException.getCause() == null) { + throw new Exception(("Configuration error. " + configurationException.getMessage())); + } else { + throw new Exception( + ("Error reading configuration. " + configurationException.getCause().getMessage()), + configurationException.getCause()); + } + } + } + + public static void addWatermark(ClassStorage classStorage) throws ObfuscationException { + new WatermarkProcessor(classStorage, Configuration.getWatermarkOptions().getText2()) + .processText(Configuration.getWatermarkOptions().getText()); + } + + public static String extractWatermark(ClassStorage classStorage) throws ObfuscationException { + return new WatermarkProcessor(classStorage, Configuration.getWatermarkOptions().getText2()) + .createText(); + } + + public static void writeAllOutputs(ClassStorage classStorage) + throws IOException, FileNotFoundException, ClassNotFoundException { + writeOutputs(classStorage); + writeDirectoryOutputs(classStorage); + } + + public static StringBuffer getStringBuffer(StringBuffer stringBuffer, char value, int value2) { + int value3; + for (int value4 = value3 = 0; value4 < value2; value4 = value3) { + value3++; + stringBuffer.append(value); + } + return stringBuffer; + } + + public static boolean loadConfigurationSafely(String text) { + return loadConfigurationSafely(text, false); + } + + public static String getBanner() { + String text = " ## # # ## ### ### ## ###"; + String text2 = "Java bytecode obfuscator"; + String text3 = "" + VersionInfo.getProductName() + " " + VersionInfo.getVersion(); + String website = VersionInfo.getWebsite(); + int value = + Math.max( + text.length(), Math.max(text3.length(), Math.max(website.length(), text2.length()))); + value += 4; + StringBuffer stringBuffer; + getStringBuffer(stringBuffer = new StringBuffer("\n"), '#', value).append("\n#"); + getStringBuffer(stringBuffer, ' ', value - 2).append("#\n#"); + int value2 = (value - text.length() - 2) / 2; + int value3 = value - value2 - text.length() - 2; + if (value2 > value3) { + value3++; + value2--; + } + getStringBuffer(stringBuffer, ' ', value2).append(text); + getStringBuffer(stringBuffer, ' ', value3).append("#\n#"); + getStringBuffer(stringBuffer, ' ', value2).append((String) "# # # # # # # # # # # # "); + getStringBuffer(stringBuffer, ' ', value3).append("#\n#"); + getStringBuffer(stringBuffer, ' ', value2).append((String) "### # # ### # # # ## # "); + getStringBuffer(stringBuffer, ' ', value3).append("#\n#"); + getStringBuffer(stringBuffer, ' ', value2).append((String) "# # ### ### # # # ### # # ###"); + getStringBuffer(stringBuffer, ' ', value3).append("#\n#"); + int value4 = (value - text2.length() - 2) / 2; + int value5 = value - value4 - text2.length() - 2; + if (value4 > value5) { + value5++; + value4--; + } + getStringBuffer(stringBuffer, ' ', value - 2).append("#\n#"); + getStringBuffer(stringBuffer, ' ', value4).append(text2); + getStringBuffer(stringBuffer, ' ', value5).append("#\n#"); + getStringBuffer(stringBuffer, ' ', value - 2).append("#\n#"); + int value6 = (value - text3.length() - 2) / 2; + int value7 = value - value6 - text3.length() - 2; + if (value6 > value7) { + value7++; + value6--; + } + getStringBuffer(stringBuffer, ' ', value6).append(text3); + getStringBuffer(stringBuffer, ' ', value7).append("#\n#"); + getStringBuffer(stringBuffer, ' ', value - 2).append("#\n#"); + int value8 = (value - website.length() - 2) / 2; + int value9 = value - value8 - website.length() - 2; + if (value8 > value9) { + value9++; + value8--; + } + getStringBuffer(stringBuffer, ' ', value8).append(website); + getStringBuffer(stringBuffer, ' ', value9).append("#\n#"); + getStringBuffer(stringBuffer, ' ', value - 2).append("#\n"); + getStringBuffer(stringBuffer, '#', value).append("\n"); + return stringBuffer.toString(); + } + + public static boolean loadConfigurationSafely(String text, boolean matches) { + try { + Configuration.processEnabled(text, matches); + return true; + } catch (ConfigurationException configurationException) { + if (configurationException.getCause() == null) { + Log.error("Configuration error. " + configurationException.getMessage()); + } else { + Log.error("Error reading configuration. " + configurationException.getCause().getMessage()); + } + return false; + } + } + + public static ClassStorage createClassStorage() throws IOException { + ClassStorage classStorage = new ClassStorage(createClassLoader()); + Iterator iterator2; + Iterator iterator3 = iterator2 = Configuration.getInputOptions().getValues().iterator(); + while (iterator3.hasNext()) { + InputJar inputJar = (InputJar) iterator2.next(); + iterator3 = iterator2; + JarClassReader.processClassStorage(inputJar.text2, classStorage); + } + Iterator iterator4; + iterator3 = iterator4 = Configuration.getInputOptions().getValues3().iterator(); + while (iterator3.hasNext()) { + InputEntry inputEntry = (InputEntry) iterator4.next(); + iterator3 = iterator4; + JarClassReader.processClassStorage(inputEntry.text2, classStorage); + } + Iterator iterator5; + iterator3 = iterator5 = Configuration.getInputOptions().getValues2().iterator(); + while (iterator3.hasNext()) { + ClassPathEntry classPathEntry = (ClassPathEntry) iterator5.next(); + iterator3 = iterator5; + DirectoryClassReader.processText(classPathEntry.text, classStorage, classPathEntry.text); + } + return classStorage; + } + + public static ClassStorageClassLoader createClassLoader() { + Vector values = Configuration.getClassPathOptions().getValues(); + int value; + for (int value2 = value = 0; value2 < values.size(); value2 = ++value) { + try { + values.set(value, new File((String) values.get(value)).toURL()); + } catch (Exception exception) { + exception.printStackTrace(); + } + } + URL[] uRLs = (URL[]) values.toArray(new URL[0]); + return new ClassStorageClassLoader(uRLs); + } + + public static void writeDirectoryOutputs(ClassStorage classStorage) + throws FileNotFoundException, IOException, ClassNotFoundException { + DirectoryWriter directoryWriter = new DirectoryWriter(); + Iterator iterator2; + Iterator iterator3 = iterator2 = Configuration.getInputOptions().getValues2().iterator(); + while (iterator3.hasNext()) { + ClassPathEntry classPathEntry = (ClassPathEntry) iterator2.next(); + iterator3 = iterator2; + directoryWriter.processClassStorage(classPathEntry.text, classPathEntry.text2, classStorage); + } + } +} diff --git a/src/main/java/com/allatori/config/ClassPathEntry.java b/src/main/java/com/allatori/config/ClassPathEntry.java new file mode 100644 index 0000000..7eb6235 --- /dev/null +++ b/src/main/java/com/allatori/config/ClassPathEntry.java @@ -0,0 +1,14 @@ +package com.allatori.config; + +public class ClassPathEntry { + + public String text; + + public String text2; + + public ClassPathEntry(String text, String text2) { + super(); + this.text = text; + this.text2 = text2; + } +} diff --git a/src/main/java/com/allatori/config/ClassPathOptions.java b/src/main/java/com/allatori/config/ClassPathOptions.java new file mode 100644 index 0000000..c06feae --- /dev/null +++ b/src/main/java/com/allatori/config/ClassPathOptions.java @@ -0,0 +1,24 @@ +package com.allatori.config; + +import java.util.Vector; + +public class ClassPathOptions { + + public final Configuration configuration; + + public Vector values; + + public void processText(String text) { + this.values.add(text); + } + + public Vector getValues() { + return this.values; + } + + public ClassPathOptions(Configuration configuration2) { + super(); + this.configuration = configuration2; + this.values = new Vector(); + } +} diff --git a/src/main/java/com/allatori/config/Configuration.java b/src/main/java/com/allatori/config/Configuration.java new file mode 100644 index 0000000..e14ef70 --- /dev/null +++ b/src/main/java/com/allatori/config/Configuration.java @@ -0,0 +1,153 @@ +package com.allatori.config; + +import com.allatori.util.random.RandomUtils; + +public class Configuration { + + public ObfuscationOptions obfuscationOptions; + + public OutputOptions outputOptions = new OutputOptions(this); + + public LogOptions logOptions; + + public MethodRemovalOptions methodRemovalOptions; + + public MemberOrderOptions memberOrderOptions; + + public WatermarkOptions watermarkOptions; + + public static Configuration configuration = null; + + public RenamingOptions renamingOptions; + + public DebugInfoOptions debugInfoOptions; + + public SyntheticOptions syntheticOptions; + + public IgnoreClassesOptions ignoreClassesOptions; + + public OptimizationOptions optimizationOptions; + + public FieldRemovalOptions fieldRemovalOptions; + + public MethodCallRemovalOptions methodCallRemovalOptions; + + public ClassPathOptions classPathOptions; + + public PackageRenamingOptions packageRenamingOptions; + + public InputOptions inputOptions = new InputOptions(this); + + public MappingOptions mappingOptions; + + public ExtensiveFlowOptions extensiveFlowOptions; + + public static MemberOrderOptions getMemberOrderOptions() { + return configuration.memberOrderOptions; + } + + public static void processText(String text) throws ConfigurationException { + processEnabled(text, false); + } + + public static InputOptions getInputOptions() { + return configuration.inputOptions; + } + + public static IgnoreClassesOptions getIgnoreClassesOptions() { + return configuration.ignoreClassesOptions; + } + + public static RenamingOptions getRenamingOptions() { + return configuration.renamingOptions; + } + + public static MethodCallRemovalOptions getMethodCallRemovalOptions() { + return configuration.methodCallRemovalOptions; + } + + public static ExtensiveFlowOptions getExtensiveFlowOptions() { + return configuration.extensiveFlowOptions; + } + + public static void processEnabled(String text, boolean matches) throws ConfigurationException { + configuration = new Configuration(); + configuration.watermarkOptions.setEnabled(matches); + new XmlParsingContext(text).parse(); + RandomUtils.update(); + if (getObfuscationOptions().getCharacter() == '\uffff') { + getObfuscationOptions().setCharacter((char) (RandomUtils.calculateCount(125) + 1)); + } + } + + public static MethodRemovalOptions getMethodRemovalOptions() { + return configuration.methodRemovalOptions; + } + + public static SyntheticOptions getSyntheticOptions() { + return configuration.syntheticOptions; + } + + public static ClassPathOptions getClassPathOptions() { + return configuration.classPathOptions; + } + + public static FieldRemovalOptions getFieldRemovalOptions() { + return configuration.fieldRemovalOptions; + } + + public Configuration() { + this.classPathOptions = new ClassPathOptions(this); + this.renamingOptions = new RenamingOptions(this); + this.watermarkOptions = new WatermarkOptions(this); + this.obfuscationOptions = new ObfuscationOptions(this); + this.debugInfoOptions = new DebugInfoOptions(this); + this.extensiveFlowOptions = new ExtensiveFlowOptions(this); + this.syntheticOptions = new SyntheticOptions(this); + this.memberOrderOptions = new MemberOrderOptions(this); + this.methodCallRemovalOptions = new MethodCallRemovalOptions(this); + this.optimizationOptions = new OptimizationOptions(this); + this.fieldRemovalOptions = new FieldRemovalOptions(this); + this.packageRenamingOptions = new PackageRenamingOptions(this); + this.ignoreClassesOptions = new IgnoreClassesOptions(this); + this.logOptions = new LogOptions(this); + this.methodRemovalOptions = new MethodRemovalOptions(this); + this.mappingOptions = new MappingOptions(this); + } + + public static OptimizationOptions getOptimizationOptions() { + return configuration.optimizationOptions; + } + + public static void update() { + configuration = null; + } + + public static WatermarkOptions getWatermarkOptions() { + return configuration.watermarkOptions; + } + + public static LogOptions getLogOptions() { + return configuration.logOptions; + } + + public static DebugInfoOptions getDebugInfoOptions() { + return configuration.debugInfoOptions; + } + + public static MappingOptions getMappingOptions() { + return configuration.mappingOptions; + } + + public static PackageRenamingOptions getPackageRenamingOptions() { + return configuration.packageRenamingOptions; + } + + public static ObfuscationOptions getObfuscationOptions() { + return configuration.obfuscationOptions; + } + + public static OutputOptions getOutputOptions() { + return configuration.outputOptions; + } +} diff --git a/src/main/java/com/allatori/config/ConfigurationConstructorToken.java b/src/main/java/com/allatori/config/ConfigurationConstructorToken.java new file mode 100644 index 0000000..d65ca7c --- /dev/null +++ b/src/main/java/com/allatori/config/ConfigurationConstructorToken.java @@ -0,0 +1,3 @@ +package com.allatori.config; + +public class ConfigurationConstructorToken {} diff --git a/src/main/java/com/allatori/config/ConfigurationException.java b/src/main/java/com/allatori/config/ConfigurationException.java new file mode 100644 index 0000000..ab8845f --- /dev/null +++ b/src/main/java/com/allatori/config/ConfigurationException.java @@ -0,0 +1,12 @@ +package com.allatori.config; + +public class ConfigurationException extends Exception { + + public ConfigurationException(Throwable throwable) { + super(throwable); + } + + public ConfigurationException(String text) { + super(text); + } +} diff --git a/src/main/java/com/allatori/config/ConfigurationHandler.java b/src/main/java/com/allatori/config/ConfigurationHandler.java new file mode 100644 index 0000000..1b75f48 --- /dev/null +++ b/src/main/java/com/allatori/config/ConfigurationHandler.java @@ -0,0 +1,2472 @@ +package com.allatori.config; + +import com.allatori.config.rule.ClassRule; +import com.allatori.config.rule.FieldRule; +import com.allatori.config.rule.MethodRule; +import com.allatori.config.rule.RuleEntry; +import com.allatori.config.rule.TemplateUtils; +import com.allatori.naming.generator.LowercaseConfusableNameGenerator; +import com.allatori.naming.generator.MixedConfusableNameGenerator; +import com.allatori.util.FileUtils; +import com.allatori.util.Log; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; +import java.util.Enumeration; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.xml.sax.Attributes; +import org.xml.sax.Locator; +import org.xml.sax.helpers.DefaultHandler; + +public class ConfigurationHandler extends DefaultHandler { + + public static final int COUNT = -1; + + public static final int COUNT2 = 1; + + public String text; + + public String text2; + + public static final int COUNT3 = 3; + + public Locator locator; + + public int count; + + public boolean enabled; + + public static final int COUNT4 = 2; + + public final XmlParsingContext xmlParsingContext; + + public boolean enabled2; + + public ClassRule classRule; + + @Override + public void startElement(String text3, String text4, String text5, Attributes attributes) + throws ConfigurationSaxException { + if (!"config".equals(text5)) { + if (!"keep-names".equals(text5)) { + if ("ignore-classes".equals(text5)) { + this.enabled2 = true; + } else if ("jars".equals(text5) || "input".equals(text5)) { + this.count = 1; + this.text2 = this.createText(attributes, "basedir", false, "", true); + this.text2 = this.createText(this.text2); + if (!"".equals(this.text2) && !this.matchesText(this.text2)) { + throw new ConfigurationSaxException( + this.xmlParsingContext, + new StringBuilder() + .insert(0, "Invalid base directory '") + .append(this.text2) + .append("'. ") + .append(this.createText()) + .toString()); + } + String text6; + if ((text6 = this.createText(attributes, "single-jar", false, null, true)) != null + && !new File(text6).isAbsolute()) { + try { + text6 = new File(("" + this.text2 + File.separator + text6)).getCanonicalPath(); + } catch (Exception exception) { + text6 = new File(("" + this.text2 + File.separator + text6)).getAbsolutePath(); + } + } + Configuration.getInputOptions().setText(text6); + } else if ("jar".equals(text5) && this.count == 1) { + String text7 = this.createText(attributes, "in", true, "", true); + String text8 = + this.createText( + attributes, "out", !Configuration.getWatermarkOptions().isEnabled(), "", true); + this.processText2(text7, text8); + } else if ("nested".equals(text5) && this.count == 1) { + this.processText4(this.createText(attributes, "in", true, "", true)); + } else if ("dir".equals(text5) && this.count == 1) { + String text9 = this.createText(attributes, "in", true, "", true); + String text10 = + this.createText( + attributes, "out", !Configuration.getWatermarkOptions().isEnabled(), "", true); + this.processText4(text9, text10); + } else { + if ("jar".equals(text5) && this.count == 2) { + String[] texts = + this.createText(attributes, "name", true, "", true).split(File.pathSeparator); + int value; + for (int value2 = value = 0; value2 < texts.length; value2 = value) { + int value3 = value; + value++; + this.processText3(texts[value3]); + } + } else if ("classpath".equals(text5)) { + this.count = 2; + this.text = this.createText(attributes, "basedir", false, "", true); + this.text = this.createText(this.text); + if (!"".equals(this.text) && !this.matchesText(this.text)) { + throw new ConfigurationSaxException( + this.xmlParsingContext, + new StringBuilder() + .insert(0, "Invalid base directory '") + .append(this.text) + .append("'. ") + .append(this.createText()) + .toString()); + } + } else { + if ("class".equals(text5)) { + this.count = 3; + String text11 = this.createText(attributes, "template", false, null, true); + String text12 = this.createText(attributes, "access", false, null, true); + String text13 = this.createText(attributes, "ignore", false, null, true); + String text14 = this.createText(attributes, "stop", false, null, true); + this.classRule = this.createClassRule(text11, text12, text13, text14, "template"); + if (!this.enabled2) { + Configuration.getRenamingOptions() + .getKeepNamesOptions() + .processClassRule(this.classRule); + return; + } + Configuration.getIgnoreClassesOptions().processClassRule(this.classRule); + return; + } + if ("field".equals(text5)) { + String text15 = this.createText(attributes, "template", false, null, true); + String text16 = this.createText(attributes, "access", false, null, true); + String text17 = this.createText(attributes, "stop", false, null, true); + FieldRule fieldRule = this.createFieldRule(text15, text16, text17); + if (this.count == 3) { + if (this.classRule == null) { + throw new ConfigurationSaxException( + this.xmlParsingContext, + new StringBuilder() + .insert(0, "Error in configuration. ") + .append(this.createText()) + .toString()); + } + this.classRule.processFieldRule(fieldRule); + return; + } + Configuration.getRenamingOptions().getKeepNamesOptions().processFieldRule(fieldRule); + return; + } + if ("method".equals(text5)) { + String text18 = this.createText(attributes, "template", false, null, true); + String text19 = this.createText(attributes, "access", false, null, true); + String text20 = this.createText(attributes, "parameters", false, null, true); + String text21 = this.createText(attributes, "stop", false, null, true); + MethodRule methodRule = this.createMethodRule(text18, text19, "template", text21); + if (this.count == 3) { + if (this.classRule == null) { + throw new ConfigurationSaxException( + this.xmlParsingContext, + new StringBuilder() + .insert(0, "Error in configuration. ") + .append(this.createText()) + .toString()); + } + this.classRule.processMethodRule(methodRule); + if ("keep".equals(text20)) { + ClassRule classRule2; + (classRule2 = this.classRule.createClassRule()).processMethodRule(methodRule); + LocalVariableOptions localVariableOptions = + Configuration.getRenamingOptions().getLocalVariableOptions(); + Configuration.getRenamingOptions().getLocalVariableOptions(); + localVariableOptions.processRuleEntry(new RuleEntry(5, classRule2)); + return; + } + } else { + Configuration.getRenamingOptions() + .getKeepNamesOptions() + .processMethodRule(methodRule); + if ("keep".equals(text20)) { + try { + ClassRule classRule3; + (classRule3 = new ClassRule("class *", false, false)) + .processMethodRule(methodRule); + LocalVariableOptions localVariableOptions2 = + Configuration.getRenamingOptions().getLocalVariableOptions(); + Configuration.getRenamingOptions().getLocalVariableOptions(); + localVariableOptions2.processRuleEntry(new RuleEntry(5, classRule3)); + return; + } catch (ConfigurationException configurationException) { + return; + } + } + } + } else { + if ("property".equals(text5)) { + this.processAttributes(attributes); + return; + } + if ("trial".equals(text5)) { + String text22 = this.createText(attributes, "class", true, null, true); + String text23 = this.createText(attributes, "method", true, null, true); + Configuration.getDebugInfoOptions().setText2(text22); + Configuration.getDebugInfoOptions().setText(text23); + ClassRule classRule4 = + this.createClassRule( + this.createText(attributes, "add2class", false, "private+ class *", true), + null, + null, + null, + "add2class"); + Configuration.getDebugInfoOptions() + .processRuleEntry(new RuleEntry(1, classRule4)); + MethodRule methodRule2 = + this.createMethodRule( + this.createText( + attributes, "add2method", false, "private+ (**)", true), + null, + "add2method", + null); + classRule4.processMethodRule(methodRule2); + String text24 = this.createText(attributes, "passthis", false, "no", true); + if (!"yes".equals(text24) && !"true".equals(text24)) { + Configuration.getDebugInfoOptions().setEnabled(false); + return; + } + Configuration.getDebugInfoOptions().setEnabled(true); + return; + } + if ("watermark".equals(text5)) { + String text28 = this.createText(attributes, "key", true, null, false); + if ("".equals(text28)) { + this.processText2("key"); + } + Configuration.getWatermarkOptions().setText2(text28); + if (!Configuration.getWatermarkOptions().isEnabled()) { + String text29 = this.createText(attributes, "value", true, null, false); + if ("".equals(text29)) { + this.processText2("value"); + } + Configuration.getWatermarkOptions().setText(text29); + } + return; + } + throw new ConfigurationSaxException( + this.xmlParsingContext, + new StringBuilder() + .insert(0, "Unknown tag '") + .append(text5) + .append("'. ") + .append(this.createText()) + .toString()); + } + } + } + } + } + } + + public void processText(String text, String text2) throws ConfigurationSaxException { + if (text == null && text2 == null) { + this.processText3("template", "access"); + } + } + + public void processText(String text) throws ConfigurationSaxException { + throw new ConfigurationSaxException( + this.xmlParsingContext, + new StringBuilder() + .insert(0, "Invalid '") + .append(text) + .append("' attribute. ") + .append(this.createText()) + .toString()); + } + + public String createText(String text, String text2, String text3) + throws ConfigurationSaxException { + String text4 = text; + if (text == null) { + if (!TemplateUtils.matches(text2)) { + this.processText("access"); + } + text4 = "" + text2 + text3; + } + return text4; + } + + public void processText(String text, String text2, String text3, String text4) + throws ConfigurationSaxException { + throw new ConfigurationSaxException( + this.xmlParsingContext, + new StringBuilder() + .insert(0, "Attribute '") + .append(text) + .append("' should have one of the following values: '") + .append(text2) + .append("', '") + .append(text3) + .append("' or '") + .append(text4) + .append("'. ") + .append(this.createText()) + .toString()); + } + + public void processText2(String text) throws ConfigurationSaxException { + throw new ConfigurationSaxException( + this.xmlParsingContext, + new StringBuilder() + .insert(0, "Attribute '") + .append(text) + .append("' cannot have zero length. ") + .append(this.createText()) + .toString()); + } + + public void processText( + String text, String text2, String text3, String text4, String text5, String text6) + throws ConfigurationSaxException { + throw new ConfigurationSaxException( + this.xmlParsingContext, + new StringBuilder() + .insert(0, "Attribute '") + .append(text) + .append("' should have one of the following values: '") + .append(text2) + .append("', '") + .append(text3) + .append("', '") + .append(text4) + .append("', '") + .append(text5) + .append("' or '") + .append(text6) + .append("'. ") + .append(this.createText()) + .toString()); + } + + public String createText(String text) { + if ("".equals(text) || !new File(text).isAbsolute()) { + try { + String text2; + if ((text2 = + new File(XmlParsingContext.getText(this.xmlParsingContext)) + .getCanonicalFile() + .getParent()) + != null) { + return new File(("" + text2 + File.separator + text)).getCanonicalPath(); + } + } catch (Exception exception) { + String text3; + if ((text3 = + new File(XmlParsingContext.getText(this.xmlParsingContext)) + .getAbsoluteFile() + .getParent()) + != null) { + return new File(("" + text3 + File.separator + text)).getAbsolutePath(); + } + } + } + return text; + } + + public void processAttributes(Attributes attributes) throws ConfigurationSaxException { + String text = this.createText(attributes, "name", true, null, true); + String text2 = this.createText(attributes, "value", true, null, true); + String text3 = this.createText(attributes, "apply2class", false, "private+ class *", true); + String text4 = this.createText(attributes, "apply2method", false, "private+ *(**)", true); + if ("string-encryption".equals(text)) { + Configuration.getObfuscationOptions(); + byte value = 1; + ConfigurationHandler configurationHandler; + if ("enable".equals(text2)) { + Configuration.getObfuscationOptions(); + value = 1; + configurationHandler = this; + } else if ("disable".equals(text2)) { + Configuration.getObfuscationOptions(); + value = 0; + configurationHandler = this; + } else if ("maximum".equals(text2)) { + Configuration.getObfuscationOptions(); + value = 2; + configurationHandler = this; + } else if ("maximum-with-warnings".equals(text2)) { + Configuration.getObfuscationOptions(); + value = 3; + configurationHandler = this; + } else { + configurationHandler = this; + this.processText("value", "enable", "disable", "maximum"); + } + ClassRule classRule; + (classRule = configurationHandler.createClassRule(text3, null, null, null, "apply2class")) + .processMethodRule(this.createMethodRule(text4, null, "apply2method", null)); + Configuration.getObfuscationOptions().processRuleEntry4(new RuleEntry(value, classRule)); + } else if ("member-reorder".equals(text)) { + Configuration.getObfuscationOptions(); + byte value2 = 1; + ConfigurationHandler configurationHandler2; + if ("enable".equals(text2)) { + Configuration.getObfuscationOptions(); + value2 = 1; + configurationHandler2 = this; + } else if ("disable".equals(text2)) { + Configuration.getObfuscationOptions(); + value2 = 0; + configurationHandler2 = this; + } else if ("random".equals(text2)) { + Configuration.getObfuscationOptions(); + value2 = 1; + configurationHandler2 = this; + } else if ("alphabetical".equals(text2)) { + Configuration.getObfuscationOptions(); + value2 = 100; + configurationHandler2 = this; + } else if ("reverse-alphabetical".equals(text2)) { + Configuration.getObfuscationOptions(); + value2 = 101; + configurationHandler2 = this; + } else { + configurationHandler2 = this; + this.processText( + "value", "enable", "disable", "random", "alphabetical", "reverse-alphabetical"); + } + ClassRule classRule2 = + configurationHandler2.createClassRule(text3, null, null, null, "apply2class"); + Configuration.getObfuscationOptions().processRuleEntry6(new RuleEntry(value2, classRule2)); + } else if ("control-flow-obfuscation".equals(text)) { + byte value3 = 1; + ConfigurationHandler configurationHandler3; + if ("enable".equals(text2)) { + value3 = 1; + configurationHandler3 = this; + } else if ("disable".equals(text2)) { + value3 = 0; + configurationHandler3 = this; + } else { + configurationHandler3 = this; + this.processText("value", "enable", "disable"); + } + ClassRule classRule3; + (classRule3 = configurationHandler3.createClassRule(text3, null, null, null, "apply2class")) + .processMethodRule(this.createMethodRule(text4, null, "apply2method", null)); + Configuration.getObfuscationOptions().processRuleEntry3(new RuleEntry(value3, classRule3)); + } else if ("local-variables-naming".equals(text)) { + Configuration.getRenamingOptions().getLocalVariableOptions(); + byte value4 = 6; + if (text2.contains(":")) { + Configuration.getRenamingOptions() + .getLocalVariableOptions() + .setLocalVariablesNaming(text2.substring(text2.indexOf(58) + 1)); + text2 = text2.substring(0, text2.indexOf(58)); + } + if ("single-name".equals(text2)) { + Configuration.getRenamingOptions().getLocalVariableOptions(); + value4 = 1; + } else if ("abc".equals(text2)) { + Configuration.getRenamingOptions().getLocalVariableOptions(); + value4 = 2; + } else if ("keep".equals(text2)) { + Configuration.getRenamingOptions().getLocalVariableOptions(); + value4 = 3; + } else if ("remove".equals(text2)) { + Configuration.getRenamingOptions().getLocalVariableOptions(); + value4 = 4; + } else if ("keep-parameters".equals(text2)) { + Configuration.getRenamingOptions().getLocalVariableOptions(); + value4 = 5; + } else if ("optimize".equals(text2)) { + Configuration.getRenamingOptions().getLocalVariableOptions(); + value4 = 6; + } else { + this.processText( + "value", "single-name", "abc", "keep", "remove", "keep-parameters", "optimize"); + } + if ("private+ class *".equals(text3) && "private+ *(**)".equals(text4)) { + Configuration.getRenamingOptions() + .getLocalVariableOptions() + .setLocalVariablesNamingMode(value4); + } + ClassRule classRule4; + (classRule4 = this.createClassRule(text3, null, null, null, "apply2class")) + .processMethodRule(this.createMethodRule(text4, null, "apply2method", null)); + Configuration.getRenamingOptions() + .getLocalVariableOptions() + .processRuleEntry(new RuleEntry(value4, classRule4)); + } else if ("packages-naming".equals(text)) { + if ("abc".equals(text2)) { + NameGenerationOptions nameGenerationOptions = + Configuration.getRenamingOptions().getNameGenerationOptions(); + Configuration.getRenamingOptions().getNameGenerationOptions(); + nameGenerationOptions.setPackagesNamingMode(1); + } else if ("ABC".equals(text2)) { + NameGenerationOptions nameGenerationOptions2 = + Configuration.getRenamingOptions().getNameGenerationOptions(); + Configuration.getRenamingOptions().getNameGenerationOptions(); + nameGenerationOptions2.setPackagesNamingMode(8); + } else if ("123".equals(text2)) { + NameGenerationOptions nameGenerationOptions3 = + Configuration.getRenamingOptions().getNameGenerationOptions(); + Configuration.getRenamingOptions().getNameGenerationOptions(); + nameGenerationOptions3.setPackagesNamingMode(6); + } else if ("keep".equals(text2)) { + Configuration.getRenamingOptions().setEnabled(true); + } else if (text2.startsWith("custom(")) { + NameGenerationOptions nameGenerationOptions4 = + Configuration.getRenamingOptions().getNameGenerationOptions(); + Configuration.getRenamingOptions().getNameGenerationOptions(); + nameGenerationOptions4.setPackagesNamingMode(7); + Configuration.getRenamingOptions() + .getNameGenerationOptions() + .setTexts4(this.createTexts(text2)); + } else { + this.processText("value", "abc", "ABC", "123", "keep", "custom(filename.txt)"); + } + } else { + if ("classes-naming".equals(text)) { + int value5 = -1; + if (text2.indexOf(40) > 0 && !text2.startsWith("custom(")) { + String text5; + label867: + { + try { + value5 = Integer.valueOf(text2.substring(text2.indexOf(40) + 1, text2.indexOf(41))); + } catch (Exception exception) { + text5 = text2; + break label867; + } + text5 = text2; + } + text2 = text5.substring(0, text2.indexOf(40)); + } + if ("abc".equals(text2)) { + NameGenerationOptions nameGenerationOptions5 = + Configuration.getRenamingOptions().getNameGenerationOptions(); + Configuration.getRenamingOptions().getNameGenerationOptions(); + nameGenerationOptions5.setClassesNamingMode(1); + return; + } + if ("ABC".equals(text2)) { + NameGenerationOptions nameGenerationOptions6 = + Configuration.getRenamingOptions().getNameGenerationOptions(); + Configuration.getRenamingOptions().getNameGenerationOptions(); + nameGenerationOptions6.setClassesNamingMode(8); + return; + } + if ("compact".equals(text2)) { + NameGenerationOptions nameGenerationOptions7 = + Configuration.getRenamingOptions().getNameGenerationOptions(); + Configuration.getRenamingOptions().getNameGenerationOptions(); + nameGenerationOptions7.setClassesNamingMode(2); + return; + } + if ("windows".equals(text2)) { + NameGenerationOptions nameGenerationOptions8 = + Configuration.getRenamingOptions().getNameGenerationOptions(); + Configuration.getRenamingOptions().getNameGenerationOptions(); + nameGenerationOptions8.setClassesNamingMode(4); + return; + } + if ("iii".equals(text2)) { + NameGenerationOptions nameGenerationOptions9 = + Configuration.getRenamingOptions().getNameGenerationOptions(); + Configuration.getRenamingOptions().getNameGenerationOptions(); + nameGenerationOptions9.setClassesNamingMode(5); + if (value5 > 0) { + MixedConfusableNameGenerator.processCount(value5); + return; + } + } else { + if (!"lll".equals(text2) + && !"ll1".equals(text2) + && !"l1l".equals(text2) + && !"l11".equals(text2) + && !"1ll".equals(text2) + && !"1l1".equals(text2) + && !"11l".equals(text2) + && !"111".equals(text2)) { + if ("123".equals(text2)) { + NameGenerationOptions nameGenerationOptions10 = + Configuration.getRenamingOptions().getNameGenerationOptions(); + Configuration.getRenamingOptions().getNameGenerationOptions(); + nameGenerationOptions10.setClassesNamingMode(6); + return; + } + if (text2.startsWith("custom(")) { + NameGenerationOptions nameGenerationOptions11 = + Configuration.getRenamingOptions().getNameGenerationOptions(); + Configuration.getRenamingOptions().getNameGenerationOptions(); + nameGenerationOptions11.setClassesNamingMode(7); + Configuration.getRenamingOptions() + .getNameGenerationOptions() + .setTexts3(this.createTexts(text2)); + return; + } + if ("unique".equals(text2)) { + Configuration.getRenamingOptions().getNameGenerationOptions().setEnabled2(true); + return; + } + if ("keep-$-sign".equals(text2)) { + Configuration.getRenamingOptions().setEnabled4(true); + return; + } + this.processText( + "value", + "abc", + "ABC", + "compact", + "windows", + "iii", + "lll", + "123", + "unique", + "keep-$-sign", + "custom(filename.txt)"); + return; + } + NameGenerationOptions nameGenerationOptions12 = + Configuration.getRenamingOptions().getNameGenerationOptions(); + Configuration.getRenamingOptions().getNameGenerationOptions(); + nameGenerationOptions12.setClassesNamingMode(9); + if (value5 > 0) { + LowercaseConfusableNameGenerator.processCount(value5); + return; + } + } + } else if ("fields-naming".equals(text)) { + int value6 = -1; + if (text2.indexOf(40) > 0 && !text2.startsWith("custom(")) { + String text6; + label877: + { + try { + value6 = Integer.valueOf(text2.substring(text2.indexOf(40) + 1, text2.indexOf(41))); + } catch (Exception exception2) { + text6 = text2; + break label877; + } + text6 = text2; + } + text2 = text6.substring(0, text2.indexOf(40)); + } + if ("abc".equals(text2)) { + NameGenerationOptions nameGenerationOptions13 = + Configuration.getRenamingOptions().getNameGenerationOptions(); + Configuration.getRenamingOptions().getNameGenerationOptions(); + nameGenerationOptions13.setFieldsNamingMode(1); + return; + } + if ("ABC".equals(text2)) { + NameGenerationOptions nameGenerationOptions14 = + Configuration.getRenamingOptions().getNameGenerationOptions(); + Configuration.getRenamingOptions().getNameGenerationOptions(); + nameGenerationOptions14.setFieldsNamingMode(8); + return; + } + if ("compact".equals(text2)) { + NameGenerationOptions nameGenerationOptions15 = + Configuration.getRenamingOptions().getNameGenerationOptions(); + Configuration.getRenamingOptions().getNameGenerationOptions(); + nameGenerationOptions15.setFieldsNamingMode(2); + return; + } + if ("keywords".equals(text2)) { + NameGenerationOptions nameGenerationOptions16 = + Configuration.getRenamingOptions().getNameGenerationOptions(); + Configuration.getRenamingOptions().getNameGenerationOptions(); + nameGenerationOptions16.setFieldsNamingMode(3); + return; + } + if ("iii".equals(text2)) { + NameGenerationOptions nameGenerationOptions17 = + Configuration.getRenamingOptions().getNameGenerationOptions(); + Configuration.getRenamingOptions().getNameGenerationOptions(); + nameGenerationOptions17.setFieldsNamingMode(5); + if (value6 > 0) { + MixedConfusableNameGenerator.processCount(value6); + return; + } + } else { + if (!"lll".equals(text2) + && !"ll1".equals(text2) + && !"l1l".equals(text2) + && !"l11".equals(text2) + && !"1ll".equals(text2) + && !"1l1".equals(text2) + && !"11l".equals(text2) + && !"111".equals(text2)) { + if ("123".equals(text2)) { + NameGenerationOptions nameGenerationOptions18 = + Configuration.getRenamingOptions().getNameGenerationOptions(); + Configuration.getRenamingOptions().getNameGenerationOptions(); + nameGenerationOptions18.setFieldsNamingMode(6); + return; + } + if ("real".equals(text2)) { + Configuration.getRenamingOptions().getNameGenerationOptions().setEnabled(true); + return; + } + if ("unique".equals(text2)) { + Configuration.getRenamingOptions().setEnabled6(true); + return; + } + if (text2.startsWith("custom(")) { + NameGenerationOptions nameGenerationOptions19 = + Configuration.getRenamingOptions().getNameGenerationOptions(); + Configuration.getRenamingOptions().getNameGenerationOptions(); + nameGenerationOptions19.setFieldsNamingMode(7); + Configuration.getRenamingOptions() + .getNameGenerationOptions() + .setTexts2(this.createTexts(text2)); + return; + } + this.processText( + "value", + "abc", + "ABC", + "compact", + "keywords", + "iii", + "lll", + "123", + "real", + "unique", + "custom(filename.txt)"); + return; + } + NameGenerationOptions nameGenerationOptions20 = + Configuration.getRenamingOptions().getNameGenerationOptions(); + Configuration.getRenamingOptions().getNameGenerationOptions(); + nameGenerationOptions20.setFieldsNamingMode(9); + if (value6 > 0) { + LowercaseConfusableNameGenerator.processCount(value6); + return; + } + } + } else if ("methods-naming".equals(text)) { + int value7 = -1; + if (text2.indexOf(40) > 0 && !text2.startsWith("custom(")) { + String text7; + label887: + { + try { + value7 = Integer.valueOf(text2.substring(text2.indexOf(40) + 1, text2.indexOf(41))); + } catch (Exception exception3) { + text7 = text2; + break label887; + } + text7 = text2; + } + text2 = text7.substring(0, text2.indexOf(40)); + } + if ("abc".equals(text2)) { + NameGenerationOptions nameGenerationOptions21 = + Configuration.getRenamingOptions().getNameGenerationOptions(); + Configuration.getRenamingOptions().getNameGenerationOptions(); + nameGenerationOptions21.setMethodsNamingMode(1); + return; + } + if ("ABC".equals(text2)) { + NameGenerationOptions nameGenerationOptions22 = + Configuration.getRenamingOptions().getNameGenerationOptions(); + Configuration.getRenamingOptions().getNameGenerationOptions(); + nameGenerationOptions22.setMethodsNamingMode(8); + return; + } + if ("compact".equals(text2)) { + NameGenerationOptions nameGenerationOptions23 = + Configuration.getRenamingOptions().getNameGenerationOptions(); + Configuration.getRenamingOptions().getNameGenerationOptions(); + nameGenerationOptions23.setMethodsNamingMode(2); + return; + } + if ("keywords".equals(text2)) { + NameGenerationOptions nameGenerationOptions24 = + Configuration.getRenamingOptions().getNameGenerationOptions(); + Configuration.getRenamingOptions().getNameGenerationOptions(); + nameGenerationOptions24.setMethodsNamingMode(3); + return; + } + if ("iii".equals(text2)) { + NameGenerationOptions nameGenerationOptions25 = + Configuration.getRenamingOptions().getNameGenerationOptions(); + Configuration.getRenamingOptions().getNameGenerationOptions(); + nameGenerationOptions25.setMethodsNamingMode(5); + if (value7 > 0) { + MixedConfusableNameGenerator.processCount(value7); + return; + } + } else { + if (!"lll".equals(text2) + && !"ll1".equals(text2) + && !"l1l".equals(text2) + && !"l11".equals(text2) + && !"1ll".equals(text2) + && !"1l1".equals(text2) + && !"11l".equals(text2) + && !"111".equals(text2)) { + if ("123".equals(text2)) { + NameGenerationOptions nameGenerationOptions26 = + Configuration.getRenamingOptions().getNameGenerationOptions(); + Configuration.getRenamingOptions().getNameGenerationOptions(); + nameGenerationOptions26.setMethodsNamingMode(6); + return; + } + if ("real".equals(text2)) { + Configuration.getRenamingOptions().getNameGenerationOptions().setEnabled3(true); + return; + } + if ("unique".equals(text2)) { + Configuration.getRenamingOptions().setEnabled8(true); + return; + } + if (text2.startsWith("custom(")) { + NameGenerationOptions nameGenerationOptions27 = + Configuration.getRenamingOptions().getNameGenerationOptions(); + Configuration.getRenamingOptions().getNameGenerationOptions(); + nameGenerationOptions27.setMethodsNamingMode(7); + Configuration.getRenamingOptions() + .getNameGenerationOptions() + .setTexts(this.createTexts(text2)); + return; + } + this.processText( + "value", + "abc", + "ABC", + "compact", + "keywords", + "iii", + "lll", + "123", + "real", + "unique", + "custom(filename.txt)"); + return; + } + NameGenerationOptions nameGenerationOptions28 = + Configuration.getRenamingOptions().getNameGenerationOptions(); + Configuration.getRenamingOptions().getNameGenerationOptions(); + nameGenerationOptions28.setMethodsNamingMode(9); + if (value7 > 0) { + LowercaseConfusableNameGenerator.processCount(value7); + return; + } + } + } else { + if ("default-package".equals(text)) { + String text8; + String text9 = text8 = this.createText(attributes, "value", true, null, false); + while (text9.endsWith(".")) { + text9 = text8 = text8.substring(0, text8.length() - 1); + } + Configuration.getRenamingOptions().setDefaultPackage(text8); + return; + } + if ("force-default-package".equals(text)) { + if ("enable".equals(text2)) { + Configuration.getRenamingOptions().setEnabled7(true); + return; + } + if ("disable".equals(text2)) { + Configuration.getRenamingOptions().setEnabled7(false); + return; + } + this.processText("value", "enable", "disable"); + return; + } + if ("line-numbers".equals(text)) { + if ("keep".equals(text2)) { + LineNumberOptions lineNumberOptions = + Configuration.getRenamingOptions().getLineNumberOptions(); + Configuration.getRenamingOptions().getLineNumberOptions(); + lineNumberOptions.setLineNumbersMode(2); + return; + } + if ("remove".equals(text2)) { + LineNumberOptions lineNumberOptions2 = + Configuration.getRenamingOptions().getLineNumberOptions(); + Configuration.getRenamingOptions().getLineNumberOptions(); + lineNumberOptions2.setLineNumbersMode(3); + return; + } + if ("obfuscate".equals(text2)) { + LineNumberOptions lineNumberOptions3 = + Configuration.getRenamingOptions().getLineNumberOptions(); + Configuration.getRenamingOptions().getLineNumberOptions(); + lineNumberOptions3.setLineNumbersMode(1); + return; + } + this.processText("value", "keep", "remove", "obfuscate"); + return; + } + if ("log-file".equals(text)) { + if (text2.length() == 0) { + this.processText("value"); + } + if (!new File(text2).isAbsolute()) { + try { + String text10; + if ((text10 = + new File(XmlParsingContext.getText(this.xmlParsingContext)) + .getCanonicalFile() + .getParent()) + != null) { + text2 = new File(("" + text10 + File.separator + text2)).getCanonicalPath(); + } + } catch (Exception exception4) { + String text11; + if ((text11 = + new File(XmlParsingContext.getText(this.xmlParsingContext)) + .getAbsoluteFile() + .getParent()) + != null) { + text2 = new File(("" + text11 + File.separator + text2)).getAbsolutePath(); + } + } + } + Configuration.getOutputOptions().setLogFile(text2); + return; + } + if ("random-seed".equals(text)) { + Configuration.getObfuscationOptions().setRandomSeed(text2); + return; + } + if ("incremental-obfuscation".equals(text)) { + if (text2.length() == 0) { + this.processText("value"); + } + if (!new File(text2).isAbsolute()) { + try { + String text12; + if ((text12 = + new File(XmlParsingContext.getText(this.xmlParsingContext)) + .getCanonicalFile() + .getParent()) + != null) { + text2 = new File(("" + text12 + File.separator + text2)).getCanonicalPath(); + } + } catch (Exception exception5) { + String text13; + if ((text13 = + new File(XmlParsingContext.getText(this.xmlParsingContext)) + .getAbsoluteFile() + .getParent()) + != null) { + text2 = new File(("" + text13 + File.separator + text2)).getAbsolutePath(); + } + } + } + if (!new File(text2).exists()) { + throw new ConfigurationSaxException( + this.xmlParsingContext, + new StringBuilder() + .insert(0, "Cannot find file '") + .append(text2) + .append("'. ") + .append(this.createText()) + .toString()); + } + Configuration.getRenamingOptions().setIncrementalObfuscation(text2); + return; + } + if ("string-encryption-type".equals(text)) { + Configuration.getObfuscationOptions(); + int value8 = 0; + ConfigurationHandler configurationHandler4; + if ("fast".equals(text2)) { + Configuration.getObfuscationOptions(); + value8 = 0; + configurationHandler4 = this; + } else if ("strong".equals(text2)) { + Configuration.getObfuscationOptions(); + value8 = 1; + configurationHandler4 = this; + } else { + label840: + if (text2.startsWith("custom(")) { + Configuration.getObfuscationOptions(); + value8 = 1000 + this.locator.getLineNumber(); + try { + String text14; + String text15 = text14 = text2.substring(7, text2.indexOf(44)).trim(); + String text16 = text15.substring(0, text14.lastIndexOf(46)); + String text17 = text15.substring(text14.lastIndexOf(46) + 1); + String text18; + String text19 = + text18 = text2.substring(text2.indexOf(44) + 1, text2.length() - 1).trim(); + String text20 = text19.substring(0, text18.lastIndexOf(46)); + String text21 = text19.substring(text18.lastIndexOf(46) + 1); + Configuration.getObfuscationOptions() + .getEntries() + .put(value8, new String[] {text16, text17, text20, text21}); + } catch (Exception exception6) { + configurationHandler4 = this; + this.processText( + "value", + "fast", + "strong", + "custom(ClassName.methodName, ClassName2.methodName2)"); + break label840; + } + configurationHandler4 = this; + } else { + configurationHandler4 = this; + this.processText( + "value", + "fast", + "strong", + "custom(ClassName.methodName, ClassName2.methodName2)"); + } + } + ClassRule classRule5; + (classRule5 = + configurationHandler4.createClassRule(text3, null, null, null, "apply2class")) + .processMethodRule(this.createMethodRule(text4, null, "apply2method", null)); + Configuration.getObfuscationOptions() + .processRuleEntry5(new RuleEntry(value8, classRule5)); + return; + } + if ("finalize".equals(text)) { + if ("enable".equals(text2)) { + Configuration.getObfuscationOptions().setEnabled8(true); + return; + } + if ("disable".equals(text2)) { + Configuration.getObfuscationOptions().setEnabled8(false); + return; + } + this.processText("value", "enable", "disable"); + return; + } + if ("anti-jd".equals(text) || "extensive-flow-obfuscation".equals(text)) { + Configuration.getExtensiveFlowOptions(); + byte value9 = 1; + ConfigurationHandler configurationHandler5; + if ("disable".equals(text2)) { + Configuration.getExtensiveFlowOptions(); + value9 = 0; + configurationHandler5 = this; + } else if ("normal".equals(text2)) { + Configuration.getExtensiveFlowOptions(); + value9 = 1; + configurationHandler5 = this; + } else if ("maximum".equals(text2)) { + Configuration.getExtensiveFlowOptions(); + value9 = 2; + configurationHandler5 = this; + } else { + configurationHandler5 = this; + this.processText("value", "disable", "normal", "maximum"); + } + ClassRule classRule6; + (classRule6 = + configurationHandler5.createClassRule(text3, null, null, null, "apply2class")) + .processMethodRule(this.createMethodRule(text4, null, "apply2method", null)); + Configuration.getExtensiveFlowOptions() + .processRuleEntry(new RuleEntry(value9, classRule6)); + return; + } + if ("unique-renaming".equals(text)) { + ConfigurationHandler configurationHandler6; + if ("enable".equals(text2)) { + Configuration.getRenamingOptions().setEnabled8(true); + configurationHandler6 = this; + } else if ("disable".equals(text2)) { + Configuration.getRenamingOptions().setEnabled8(false); + configurationHandler6 = this; + } else { + configurationHandler6 = this; + this.processText("value", "enable", "disable"); + } + ClassRule classRule7; + (classRule7 = + configurationHandler6.createClassRule(text3, null, null, null, "apply2class")) + .processMethodRule(this.createMethodRule(text4, null, "apply2method", null)); + RenamingOptions renamingOptions = Configuration.getRenamingOptions(); + RuleEntry ruleEntry; + byte value10; + ClassRule classRule8; + if (Configuration.getRenamingOptions().isEnabled8()) { + value10 = 1; + classRule8 = classRule7; + } else { + value10 = 0; + classRule8 = classRule7; + } + ruleEntry = new RuleEntry(value10, classRule8); + renamingOptions.processRuleEntry(ruleEntry); + return; + } + if ("randomize-names".equals(text)) { + if ("enable".equals(text2)) { + Configuration.getRenamingOptions().setEnabled3(true); + return; + } + if ("disable".equals(text2)) { + Configuration.getRenamingOptions().setEnabled3(false); + return; + } + this.processText("value", "enable", "disable"); + return; + } + if ("string-encryption-seed".equals(text)) { + if (text2.length() == 0) { + this.processText2("value"); + return; + } + Configuration.getObfuscationOptions().setCharacter(text2.charAt(0)); + return; + } + if ("string-encryption-version".equals(text)) { + ConfigurationHandler configurationHandler7; + if ("v3".equals(text2)) { + ObfuscationOptions obfuscationOptions = Configuration.getObfuscationOptions(); + Configuration.getObfuscationOptions(); + obfuscationOptions.setStringEncryptionVersion(0); + configurationHandler7 = this; + } else if ("v4".equals(text2) || "v4-per-jar".equals(text2)) { + ObfuscationOptions obfuscationOptions2 = Configuration.getObfuscationOptions(); + Configuration.getObfuscationOptions(); + obfuscationOptions2.setStringEncryptionVersion(1); + Configuration.getObfuscationOptions().setEnabled7(false); + Configuration.getObfuscationOptions().setEnabled5(false); + configurationHandler7 = this; + } else if ("v4-global".equals(text2)) { + ObfuscationOptions obfuscationOptions3 = Configuration.getObfuscationOptions(); + Configuration.getObfuscationOptions(); + obfuscationOptions3.setStringEncryptionVersion(1); + Configuration.getObfuscationOptions().setEnabled7(true); + configurationHandler7 = this; + } else if ("v4-per-package".equals(text2)) { + ObfuscationOptions obfuscationOptions4 = Configuration.getObfuscationOptions(); + Configuration.getObfuscationOptions(); + obfuscationOptions4.setStringEncryptionVersion(1); + Configuration.getObfuscationOptions().setEnabled5(true); + configurationHandler7 = this; + } else { + configurationHandler7 = this; + this.processText("value", "v3", "v4"); + } + String text22 = configurationHandler7.createText(attributes, "add", false, "", true); + String text23 = this.createText(attributes, "noadd", false, "", true); + Configuration.getObfuscationOptions().setDecryptorIncludePattern(text22); + Configuration.getObfuscationOptions().setDecryptorExcludePattern(text23); + return; + } + if ("version-marker".equals(text)) { + if (text2.length() == 0) { + this.processText2("value"); + return; + } + Configuration.getRenamingOptions().getNameGenerationOptions().processText(text2); + return; + } + if ("fields-naming-prefix".equals(text)) { + Configuration.getRenamingOptions() + .getNameGenerationOptions() + .setFieldsNamingPrefix(text2); + return; + } + if ("methods-naming-prefix".equals(text)) { + Configuration.getRenamingOptions() + .getNameGenerationOptions() + .setMethodsNamingPrefix(text2); + return; + } + if ("classes-naming-prefix".equals(text)) { + Configuration.getRenamingOptions() + .getNameGenerationOptions() + .setClassesNamingPrefix(text2); + return; + } + if ("string-encryption-ignored-strings".equals(text)) { + if (text2.length() == 0) { + this.processText("value"); + } + if (!new File(text2).isAbsolute()) { + try { + String text24; + if ((text24 = + new File(XmlParsingContext.getText(this.xmlParsingContext)) + .getCanonicalFile() + .getParent()) + != null) { + text2 = new File(("" + text24 + File.separator + text2)).getCanonicalPath(); + } + } catch (Exception exception7) { + String text25; + if ((text25 = + new File(XmlParsingContext.getText(this.xmlParsingContext)) + .getAbsoluteFile() + .getParent()) + != null) { + text2 = new File(("" + text25 + File.separator + text2)).getAbsolutePath(); + } + } + } + if (!new File(text2).exists()) { + throw new ConfigurationSaxException( + this.xmlParsingContext, + new StringBuilder() + .insert(0, "Cannot find file '") + .append(text2) + .append("'. ") + .append(this.createText()) + .toString()); + } + Configuration.getObfuscationOptions().setStringEncryptionIgnoredStrings(text2); + return; + } + if ("output-jar-comment".equals(text)) { + if (!"disable".equals(text2) && !"false".equals(text2)) { + if (!"enable".equals(text2) && !"true".equals(text2)) { + Configuration.getObfuscationOptions().setOutputJarComment(text2); + return; + } + Configuration.getObfuscationOptions().setEnabled2(true); + return; + } + Configuration.getObfuscationOptions().setEnabled2(false); + return; + } + if ("skip-renaming".equals(text)) { + if ("enable".equals(text2)) { + Configuration.getRenamingOptions().setEnabled5(true); + return; + } + if ("disable".equals(text2)) { + Configuration.getRenamingOptions().setEnabled5(false); + return; + } + this.processText("value", "enable", "disable"); + return; + } + if (!"android-detection".equals(text)) { + if ("generics".equals(text)) { + byte value11 = 0; + ConfigurationHandler configurationHandler8; + if ("remove".equals(text2)) { + value11 = 1; + configurationHandler8 = this; + } else if ("keep".equals(text2)) { + value11 = 0; + configurationHandler8 = this; + } else { + configurationHandler8 = this; + this.processText("value", "remove", "keep"); + } + ClassRule classRule9 = + configurationHandler8.createClassRule(text3, null, null, null, "apply2class"); + Configuration.getObfuscationOptions() + .processRuleEntry(new RuleEntry(value11, classRule9)); + return; + } + if ("inner-classes".equals(text)) { + byte value12 = 0; + ConfigurationHandler configurationHandler9; + if ("remove".equals(text2)) { + value12 = 1; + configurationHandler9 = this; + } else if ("keep".equals(text2)) { + value12 = 0; + configurationHandler9 = this; + } else { + configurationHandler9 = this; + this.processText("value", "remove", "keep"); + } + ClassRule classRule10 = + configurationHandler9.createClassRule(text3, null, null, null, "apply2class"); + Configuration.getObfuscationOptions() + .processRuleEntry7(new RuleEntry(value12, classRule10)); + return; + } + if ("throws-clause".equals(text)) { + byte value13 = 0; + ConfigurationHandler configurationHandler10; + if ("remove".equals(text2)) { + value13 = 1; + configurationHandler10 = this; + } else if ("keep".equals(text2)) { + value13 = 0; + configurationHandler10 = this; + } else { + configurationHandler10 = this; + this.processText("value", "remove", "keep"); + } + ClassRule classRule11; + (classRule11 = + configurationHandler10.createClassRule(text3, null, null, null, "apply2class")) + .processMethodRule(this.createMethodRule(text4, null, "apply2method", null)); + Configuration.getObfuscationOptions() + .processRuleEntry2(new RuleEntry(value13, classRule11)); + return; + } + if ("synthetize-fields".equals(text)) { + byte value14 = 1; + if ("disable".equals(text2) || "none".equals(text2)) { + value14 = 0; + text2 = "private+"; + } else if ("enable".equals(text2) || "all".equals(text2)) { + text2 = "private+"; + } + if ("private".equals(text2) + || "package".equals(text2) + || "protected".equals(text2) + || "public".equals(text2)) { + text2 = "" + text2 + " *"; + } + ClassRule classRule12 = this.createClassRule(text3, null, null, null, "apply2class"); + try { + classRule12.processFieldRule(new FieldRule(text2, false, false)); + } catch (ConfigurationException configurationException) { + throw new ConfigurationSaxException( + this.xmlParsingContext, + new StringBuilder() + .insert(0, "Invalid 'synthetize-fields' property. ") + .append(this.createText()) + .toString()); + } + Configuration.getSyntheticOptions() + .processRuleEntry(new RuleEntry(value14, classRule12)); + return; + } + if ("synthetize-methods".equals(text)) { + byte value15 = 1; + String text26; + if (!"disable".equals(text2) && !"none".equals(text2)) { + if ("enable".equals(text2) || "all".equals(text2)) { + text2 = "private+"; + } + text26 = text2; + } else { + value15 = 0; + text26 = text2 = "private+"; + } + if (text26.indexOf(40) == -1) { + text2 = "" + text2 + " *(**)"; + } + ClassRule classRule13 = this.createClassRule(text3, null, null, null, "apply2class"); + try { + classRule13.processMethodRule(new MethodRule(text2, false, false)); + } catch (ConfigurationException configurationException2) { + throw new ConfigurationSaxException( + this.xmlParsingContext, + new StringBuilder() + .insert(0, "Invalid 'synthetize-methods' property. ") + .append(this.createText()) + .toString()); + } + Configuration.getSyntheticOptions() + .processRuleEntry2(new RuleEntry(value15, classRule13)); + return; + } + if ("set-fields-to-public".equals(text)) { + byte value16 = 1; + String text27; + if (!"disable".equals(text2) && !"none".equals(text2)) { + if ("enable".equals(text2) || "all".equals(text2)) { + text2 = "private+"; + } + text27 = text2; + } else { + value16 = 0; + text27 = text2 = "private+"; + } + if (text27.indexOf(32) == -1) { + text2 = "" + text2 + " *"; + } + ClassRule classRule14 = this.createClassRule(text3, null, null, null, "apply2class"); + try { + classRule14.processFieldRule(new FieldRule(text2, false, false)); + } catch (ConfigurationException configurationException3) { + throw new ConfigurationSaxException( + this.xmlParsingContext, + new StringBuilder() + .insert(0, "Invalid 'set-fields-to-public' property. ") + .append(this.createText()) + .toString()); + } + Configuration.getMemberOrderOptions() + .processRuleEntry(new RuleEntry(value16, classRule14)); + return; + } + if ("set-methods-to-public".equals(text)) { + byte value17 = 1; + String text28; + if (!"disable".equals(text2) && !"none".equals(text2)) { + if ("enable".equals(text2) || "all".equals(text2)) { + text2 = "private+"; + } + text28 = text2; + } else { + value17 = 0; + text28 = text2 = "private+"; + } + if (text28.indexOf(40) == -1) { + text2 = "" + text2 + " *(**)"; + } + ClassRule classRule15 = this.createClassRule(text3, null, null, null, "apply2class"); + try { + classRule15.processMethodRule(new MethodRule(text2, false, false)); + } catch (ConfigurationException configurationException4) { + throw new ConfigurationSaxException( + this.xmlParsingContext, + new StringBuilder() + .insert(0, "Invalid 'set-methods-to-public' property. ") + .append(this.createText()) + .toString()); + } + Configuration.getMemberOrderOptions() + .processRuleEntry2(new RuleEntry(value17, classRule15)); + return; + } + if ("remove-calls".equals(text)) { + if (text2.length() < 3 + || !text2.contains(".") + || text2.startsWith(".") + || text2.endsWith(".")) { + this.processText("value"); + } + String text29 = text2.substring(0, text2.lastIndexOf(46)); + String text30 = text2.substring(text2.lastIndexOf(46) + 1); + ClassRule classRule16; + (classRule16 = this.createClassRule(text3, null, null, null, "apply2class")) + .processMethodRule(this.createMethodRule(text4, null, "apply2method", null)); + Configuration.getMethodCallRemovalOptions() + .processText(new RuleEntry(555, classRule16), text29, text30); + return; + } + if ("remove-methods".equals(text)) { + if (text2.length() < 3 + || !text2.contains(".") + || text2.startsWith(".") + || text2.endsWith(".")) { + this.processText("value"); + } + int value18 = text2.lastIndexOf(40); + String text31 = "(**)"; + if (value18 > 0) { + text31 = text2.substring(value18); + text2 = text2.substring(0, value18); + } + if (!text2.startsWith("class ")) { + text2 = "class " + text2; + } + String text32 = text2.substring(0, text2.lastIndexOf(46)); + String text33 = text2.substring(text2.lastIndexOf(46) + 1); + ClassRule classRule17; + (classRule17 = this.createClassRule(text32, null, null, null, "value")) + .processMethodRule(this.createMethodRule(text33 + text31, null, "value", null)); + Configuration.getOptimizationOptions().processRuleEntry2(new RuleEntry(1, classRule17)); + return; + } + if ("remove-fields".equals(text)) { + if (text2.length() < 3 + || !text2.contains(".") + || text2.startsWith(".") + || text2.endsWith(".")) { + this.processText("value"); + } + if (!text2.startsWith("class ")) { + text2 = "class " + text2; + } + String text34 = text2.substring(0, text2.lastIndexOf(46)); + String text35 = text2.substring(text2.lastIndexOf(46) + 1); + ClassRule classRule18; + (classRule18 = this.createClassRule(text34, null, null, null, "value")) + .processFieldRule(this.createFieldRule(text35, null, null)); + Configuration.getFieldRemovalOptions().processRuleEntry(new RuleEntry(1, classRule18)); + return; + } + if (!"remove-annotations".equals(text)) { + if ("remove-toString".equals(text)) { + byte value19 = 0; + ConfigurationHandler configurationHandler11; + if ("enable".equals(text2)) { + value19 = 1; + configurationHandler11 = this; + } else if ("disable".equals(text2)) { + value19 = 0; + configurationHandler11 = this; + } else { + configurationHandler11 = this; + this.processText("value", "enable", "disable"); + } + ClassRule classRule19 = + configurationHandler11.createClassRule(text3, null, null, null, "apply2class"); + Configuration.getOptimizationOptions() + .processRuleEntry(new RuleEntry(value19, classRule19)); + return; + } + if ("keep-package-names".equals(text)) { + if ("enable".equals(text2)) { + Configuration.getRenamingOptions().setEnabled(true); + return; + } + if ("disable".equals(text2)) { + Configuration.getRenamingOptions().setEnabled(false); + return; + } + this.processText("value", "enable", "disable"); + return; + } + if ("compatible-renaming".equals(text)) { + if ("enable".equals(text2)) { + Configuration.getRenamingOptions().setEnabled2(true); + return; + } + if ("disable".equals(text2)) { + Configuration.getRenamingOptions().setEnabled2(false); + return; + } + this.processText("value", "enable", "disable"); + return; + } + if ("java6".equals(text)) { + if ("enable".equals(text2)) { + Configuration.getObfuscationOptions().setEnabled4(true); + return; + } + if ("disable".equals(text2)) { + Configuration.getObfuscationOptions().setEnabled4(false); + return; + } + this.processText("value", "enable", "disable"); + return; + } + if ("update-resource-names".equals(text)) { + if ("enable".equals(text2)) { + Configuration.getRenamingOptions().getResourceRenamingOptions().setEnabled(true); + return; + } + if ("disable".equals(text2)) { + Configuration.getRenamingOptions().getResourceRenamingOptions().setEnabled(false); + return; + } + this.processText("value", "enable", "disable"); + return; + } + if ("update-resource-contents".equals(text)) { + String text36 = this.createText(attributes, "apply2file", false, "*", true); + if ("enable".equals(text2)) { + Configuration.getRenamingOptions() + .getResourceRenamingOptions() + .processText(text36, true, "UTF-8"); + return; + } + if ("disable".equals(text2)) { + Configuration.getRenamingOptions() + .getResourceRenamingOptions() + .processText(text36, false, "UTF-8"); + return; + } + if (text2.startsWith("enable:")) { + String text37 = text2.substring("enable:".length()); + try { + Charset.forName(text37); + } catch (Exception exception8) { + throw new ConfigurationSaxException( + this.xmlParsingContext, + new StringBuilder() + .insert(0, "Invalid encoding '") + .append(text37) + .append("'. ") + .append(this.createText()) + .toString()); + } + Configuration.getRenamingOptions() + .getResourceRenamingOptions() + .processText(text36, true, text37); + return; + } + this.processText("value", "enable", "enable:ENCODING", "disable"); + return; + } + if ("com-license4j-support".equals(text)) { + if (text2 != null && text2.length() > 0) { + Configuration.getLogOptions().setComLicense4jSupport(text2); + return; + } + this.processText("value"); + return; + } + if ("output-jar-compression-level".equals(text)) { + try { + int value20; + if ((value20 = Integer.valueOf(text2)) >= -1 && value20 <= 9) { + Configuration.getOutputOptions().setCompressionLevel(value20); + return; + } + this.processText("value"); + return; + } catch (Exception exception9) { + this.processText("value"); + return; + } + } + if ("output-jar-duplicate-name-entries".equals(text)) { + if ("keep".equals(text2)) { + Configuration.getOutputOptions().setEnabled(true); + return; + } + if ("remove".equals(text2)) { + Configuration.getOutputOptions().setEnabled(false); + return; + } + this.processText("value", "remove", "keep"); + return; + } + if ("test".equals(text)) { + byte value21 = 0; + ConfigurationHandler configurationHandler12; + if ("enable".equals(text2)) { + value21 = 1; + configurationHandler12 = this; + } else if ("disable".equals(text2)) { + value21 = 0; + configurationHandler12 = this; + } else { + configurationHandler12 = this; + this.processText("value", "enable", "disable"); + } + ClassRule classRule20; + (classRule20 = + configurationHandler12.createClassRule( + text3, null, null, null, "apply2class")) + .processMethodRule(this.createMethodRule(text4, null, "apply2method", null)); + Configuration.getMethodRemovalOptions() + .processRuleEntry(new RuleEntry(value21, classRule20)); + return; + } + if ("test-string".equals(text)) { + if (text2 != null && text2.length() > 0) { + Configuration.getMethodRemovalOptions().setTestString(text2); + return; + } + this.processText("value"); + return; + } + throw new ConfigurationSaxException( + this.xmlParsingContext, + new StringBuilder() + .insert(0, "Unknown property '") + .append(text) + .append("'. ") + .append(this.createText()) + .toString()); + } + if (text2.length() < 1 || text2.startsWith(".") || text2.endsWith(".")) { + this.processText("value"); + } + ClassRule classRule21 = this.createClassRule(text3, null, null, null, "apply2class"); + Configuration.getPackageRenamingOptions() + .processText(new RuleEntry(555, classRule21), text2); + return; + } + if ("disable".equals(text2) || "false".equals(text2)) { + Configuration.getObfuscationOptions().setEnabled6(false); + return; + } + } + } + } + + public void processText2(String text, String text3) throws ConfigurationSaxException { + String text4 = text; + if (this.text2.length() > 0) { + try { + if (text4 != null && !new File(text4).isAbsolute()) { + text4 = new File(("" + this.text2 + File.separator + text4)).getCanonicalPath(); + } + if (text3 != null && !new File(text3).isAbsolute()) { + text3 = new File(("" + this.text2 + File.separator + text3)).getCanonicalPath(); + } + } catch (Exception exception) { + if (text4 != null && !new File(text4).isAbsolute()) { + text4 = new File(("" + this.text2 + File.separator + text4)).getAbsolutePath(); + } + if (text3 != null && !new File(text3).isAbsolute()) { + text3 = new File(("" + this.text2 + File.separator + text3)).getAbsolutePath(); + } + } + } + if (text4 != null && text4.indexOf("*") != -1) { + String text5 = "."; + String text6 = text4; + if (text4.indexOf(File.separator) >= 0 || text6.indexOf(47) >= 0) { + int value = text6.lastIndexOf(File.separator); + if (text6.lastIndexOf(47) > value) { + value = text6.lastIndexOf(47); + } + text5 = text6.substring(0, value); + text6 = text6.substring(value + 1); + } + File file; + if (!(file = new File(text5)).isDirectory()) { + throw new ConfigurationSaxException( + this.xmlParsingContext, + new StringBuilder() + .insert(0, "Cannot find directory '") + .append(text5) + .append("'. ") + .append(this.createText()) + .toString()); + } + Pattern pattern = Pattern.compile(text6.replaceAll("\\.", "\\\\.").replaceAll("\\*", "(.*)")); + File[] files; + int value2; + for (int value3 = value2 = (files = file.listFiles()).length - 1; + value3 >= 0; + value3 = --value2) { + File file2; + Matcher matcher2; + if (!(file2 = files[value2]).isDirectory() + && (matcher2 = pattern.matcher(file2.getName())).matches()) { + String text7 = matcher2.group(1); + String absolutePath = file2.getAbsolutePath(); + String text8 = null; + if (text3 != null) { + text8 = text3.replaceFirst("\\*", text7); + } + Configuration.getInputOptions().processInputEntry(new InputEntry(absolutePath, text8)); + } + } + } else { + if (!new File(text4).exists()) { + throw new ConfigurationSaxException( + this.xmlParsingContext, + new StringBuilder() + .insert(0, "Cannot find file '") + .append(text4) + .append("'. ") + .append(this.createText()) + .toString()); + } + Configuration.getInputOptions().processInputEntry(new InputEntry(text4, text3)); + } + } + + public void processEnabled(File file, String text, boolean matches2) { + int value; + File[] files; + for (int value2 = value = (files = file.listFiles()).length - 1; + value2 >= 0; + value2 = --value) { + File file2; + if (!(file2 = files[value]).isDirectory() && file2.getName().matches(text)) { + Configuration.getClassPathOptions().processText(file2.getAbsolutePath()); + } + if (matches2 && file2.isDirectory()) { + this.processEnabled(file2, text, matches2); + } + } + } + + public ConfigurationHandler( + XmlParsingContext xmlParsingContext, + ConfigurationConstructorToken configurationConstructorToken) { + this(xmlParsingContext); + } + + public String createText( + Attributes attributes, String text, boolean matches, String text2, boolean matches2) + throws ConfigurationSaxException { + String text3; + if ((text3 = attributes.getValue(text)) == null && matches) { + throw new ConfigurationSaxException( + this.xmlParsingContext, + new StringBuilder() + .insert(0, "Missing '") + .append(text) + .append("' attribute. ") + .append(this.createText()) + .toString()); + } + if (text3 == null) { + return text2; + } + while (text3.contains("${System.getProperty(")) { + int value; + if ((value = text3.indexOf("${System.getProperty(")) >= 0) { + int value2; + if ((value2 = text3.indexOf(")}", value)) < value) { + throw new ConfigurationSaxException( + this.xmlParsingContext, + new StringBuilder() + .insert(0, "Invalid '") + .append(text) + .append("' attribute. ") + .append(this.createText()) + .toString()); + } + String text4; + String text5; + if ((text5 = System.getProperty(text4 = text3.substring(value + 21, value2))) == null) { + throw new ConfigurationSaxException( + this.xmlParsingContext, + new StringBuilder() + .insert(0, "Missing system property '") + .append(text4) + .append("'. ") + .append(this.createText()) + .toString()); + } + text3 = "" + text3.substring(0, value) + text5 + text3.substring(value2 + 2); + } + } + while (text3.contains("${System.getenv(")) { + int value3; + if ((value3 = text3.indexOf("${System.getenv(")) >= 0) { + int value4; + if ((value4 = text3.indexOf(")}", value3)) < value3) { + throw new ConfigurationSaxException( + this.xmlParsingContext, + new StringBuilder() + .insert(0, "Invalid '") + .append(text) + .append("' attribute. ") + .append(this.createText()) + .toString()); + } + String text6; + String text7; + if ((text7 = System.getenv(text6 = text3.substring(value3 + 16, value4))) == null) { + throw new ConfigurationSaxException( + this.xmlParsingContext, + new StringBuilder() + .insert(0, "Missing environment variable '") + .append(text6) + .append("'. ") + .append(this.createText()) + .toString()); + } + text3 = "" + text3.substring(0, value3) + text7 + text3.substring(value4 + 2); + } + } + return matches2 ? text3.trim() : text3; + } + + @Override + public void endElement(String text, String text2, String text3) { + if (!"jars".equals(text3) + && !"input".equals(text3) + && !"classpath".equals(text3) + && !"class".equals(text3)) { + if ("ignore-classes".equals(text3)) { + this.enabled2 = false; + } + } else { + this.count = -1; + } + } + + public void processText(String text, String text2, String text3, String text4, String text5) + throws ConfigurationSaxException { + throw new ConfigurationSaxException( + this.xmlParsingContext, + new StringBuilder() + .insert(0, "Attribute '") + .append(text) + .append("' should have one of the following values: '") + .append(text2) + .append("', '") + .append(text3) + .append("', '") + .append(text4) + .append("' or '") + .append(text5) + .append("'. ") + .append(this.createText()) + .toString()); + } + + public MethodRule createMethodRule(String text, String text2, String text3, String text4) + throws ConfigurationSaxException { + String text5 = text; + this.processText(text5, text2); + byte value = 0; + if ("yes".equals(text4) || "true".equals(text4)) { + value = 1; + } + byte value2 = 0; + if (text5 != null) { + if (text5.startsWith("!")) { + value2 = 1; + text5 = text5.substring(1).trim(); + } else if (text5.startsWith("not")) { + value2 = 1; + text5 = text5.substring(3).trim(); + } + } + try { + return new MethodRule(this.createText(text5, text2, " *(**)"), (value != 0), (value2 != 0)); + } catch (ConfigurationException configurationException) { + if (text5 != null) { + this.processText(text3); + } else { + this.processText("access"); + } + return null; + } + } + + public void processText( + String text, + String text2, + String text3, + String text4, + String text5, + String text6, + String text7, + String text8, + String text9, + String text10) + throws ConfigurationSaxException { + throw new ConfigurationSaxException( + this.xmlParsingContext, + new StringBuilder() + .insert(0, "Attribute '") + .append(text) + .append("' should have one of the following values: '") + .append(text2) + .append("', '") + .append(text3) + .append("', '") + .append(text4) + .append("', '") + .append(text5) + .append("', '") + .append(text6) + .append("', '") + .append(text7) + .append("', '") + .append(text8) + .append("', '") + .append(text9) + .append("' or '") + .append(text10) + .append("'. ") + .append(this.createText()) + .toString()); + } + + public FieldRule createFieldRule(String text, String text2, String text3) + throws ConfigurationSaxException { + String text4 = text; + this.processText(text4, text2); + byte value = 0; + if ("yes".equals(text3) || "true".equals(text3)) { + value = 1; + } + byte value2 = 0; + if (text4 != null) { + if (text4.startsWith("!")) { + value2 = 1; + text4 = text4.substring(1).trim(); + } else if (text4.startsWith("not")) { + value2 = 1; + text4 = text4.substring(3).trim(); + } + } + try { + return new FieldRule(this.createText(text4, text2, " *"), (value != 0), (value2 != 0)); + } catch (ConfigurationException configurationException) { + if (text4 != null) { + this.processText("template"); + } else { + this.processText("access"); + } + return null; + } + } + + public void processText( + String text, + String text2, + String text3, + String text4, + String text5, + String text6, + String text7, + String text8, + String text9, + String text10, + String text11) + throws ConfigurationSaxException { + throw new ConfigurationSaxException( + this.xmlParsingContext, + new StringBuilder() + .insert(0, "Attribute '") + .append(text) + .append("' should have one of the following values: '") + .append(text2) + .append("', '") + .append(text3) + .append("', '") + .append(text4) + .append("', '") + .append(text5) + .append("', '") + .append(text6) + .append("', '") + .append(text7) + .append("', '") + .append(text8) + .append("', '") + .append(text9) + .append("', '") + .append(text10) + .append("' or '") + .append(text11) + .append("'. ") + .append(this.createText()) + .toString()); + } + + public void processText3(String text2) throws ConfigurationSaxException { + String text3; + String text4; + label50: + { + text3 = text2; + label49: + if (this.text.length() > 0 && !new File(text3).isAbsolute()) { + try { + text3 = new File(("" + this.text + File.separator + text3)).getCanonicalPath(); + } catch (Exception exception) { + text3 = new File(("" + this.text + File.separator + text3)).getAbsolutePath(); + break label49; + } + text4 = text3; + break label50; + } + text4 = text3; + } + while (text4.endsWith(File.separator)) { + text4 = text3 = text3.substring(0, text3.length() - File.separator.length()); + } + if (text3.indexOf(42) == -1) { + Configuration.getClassPathOptions().processText(text3); + } else { + String text5 = "."; + String text6 = text3; + if (text3.indexOf(File.separator) >= 0 || text3.indexOf(47) >= 0) { + int value = text3.lastIndexOf(File.separator); + if (text3.lastIndexOf(47) > value) { + value = text3.lastIndexOf(47); + } + text5 = text3.substring(0, value); + text6 = text3.substring(value + 1); + } + byte value2 = 0; + if (text5.endsWith("**")) { + text5 = text5.substring(0, text5.length() - 2); + value2 = 1; + } + File file; + if (!(file = new File(text5)).isDirectory()) { + throw new ConfigurationSaxException( + this.xmlParsingContext, + new StringBuilder() + .insert(0, "Cannot find directory '") + .append(text5) + .append("'. ") + .append(this.createText()) + .toString()); + } + String text7 = text6.replaceAll("\\.", "\\\\.").replaceAll("\\*", ".*"); + this.processEnabled(file, text7, value2 != 0); + } + } + + public void processText( + String text, + String text2, + String text3, + String text4, + String text5, + String text6, + String text7, + String text8) + throws ConfigurationSaxException { + throw new ConfigurationSaxException( + this.xmlParsingContext, + new StringBuilder() + .insert(0, "Attribute '") + .append(text) + .append("' should have one of the following values: '") + .append(text2) + .append("', '") + .append(text3) + .append("', '") + .append(text4) + .append("', '") + .append(text5) + .append("', '") + .append(text6) + .append("', '") + .append(text7) + .append("' or '") + .append(text8) + .append("'. ") + .append(this.createText()) + .toString()); + } + + public void processText3(String text, String text2) throws ConfigurationSaxException { + throw new ConfigurationSaxException( + this.xmlParsingContext, + new StringBuilder() + .insert(0, "Either '") + .append(text) + .append("' or '") + .append(text2) + .append("' attribute should be defined. ") + .append(this.createText()) + .toString()); + } + + public void processText( + String text, + String text2, + String text3, + String text4, + String text5, + String text6, + String text7) + throws ConfigurationSaxException { + throw new ConfigurationSaxException( + this.xmlParsingContext, + new StringBuilder() + .insert(0, "Attribute '") + .append(text) + .append("' should have one of the following values: '") + .append(text2) + .append("', '") + .append(text3) + .append("', '") + .append(text4) + .append("', '") + .append(text5) + .append("', '") + .append(text6) + .append("' or '") + .append(text7) + .append("'. ") + .append(this.createText()) + .toString()); + } + + public void processText4(String text, String text3) throws ConfigurationSaxException { + String text4 = text; + if (this.text2.length() > 0) { + try { + if (text4 != null && !new File(text4).isAbsolute()) { + text4 = new File(("" + this.text2 + File.separator + text4)).getCanonicalPath(); + } + if (text3 != null && !new File(text3).isAbsolute()) { + text3 = new File(("" + this.text2 + File.separator + text3)).getCanonicalPath(); + } + } catch (Exception exception) { + if (text4 != null && !new File(text4).isAbsolute()) { + text4 = new File(("" + this.text2 + File.separator + text4)).getAbsolutePath(); + } + if (text3 != null && !new File(text3).isAbsolute()) { + text3 = new File(("" + this.text2 + File.separator + text3)).getAbsolutePath(); + } + } + } + if (!new File(text4).exists()) { + throw new ConfigurationSaxException( + this.xmlParsingContext, + new StringBuilder() + .insert(0, "Cannot find directory '") + .append(text4) + .append("'. ") + .append(this.createText()) + .toString()); + } + if (!new File(text4).isDirectory()) { + throw new ConfigurationSaxException( + this.xmlParsingContext, + new StringBuilder() + .insert(0, "Cannot find directory '") + .append(text4) + .append("'. ") + .append(this.createText()) + .toString()); + } + Configuration.getInputOptions().processClassPathEntry(new ClassPathEntry(text4, text3)); + } + + public void processText5(String text, String text2) throws IOException, FileNotFoundException { + Pattern pattern = Pattern.compile(text2.replaceAll("\\.", "\\\\.").replaceAll("\\*", "(.*)")); + String text3 = + new StringBuilder() + .insert(0, this.createText("allatori-tmp-nested")) + .append(File.separator) + .toString(); + File file = new File(text3); + if (this.enabled) { + this.enabled = false; + if (file.exists()) { + File[] files; + int value = (files = file.listFiles()).length; + int value2; + for (int value3 = value2 = 0; value3 < value; value3 = value2) { + File file2 = files[value2]; + value2++; + file2.delete(); + } + } else { + new File(text3).mkdirs(); + } + } + JarFile jarFile; + Enumeration enumeration = (jarFile = new JarFile(text)).entries(); + while (enumeration.hasMoreElements()) { + JarEntry jarEntry; + if (!(jarEntry = (JarEntry) enumeration.nextElement()).isDirectory() + && pattern.matcher(jarEntry.getName()).matches()) { + String name = new File(jarEntry.getName()).getName(); + byte[] values = new byte[262144]; + FileOutputStream fileOutputStream = new FileOutputStream(("" + text3 + name)); + InputStream inputStream; + InputStream inputStream2 = inputStream = jarFile.getInputStream(jarEntry); + int value4; + while ((value4 = inputStream2.read(values)) > 0) { + inputStream2 = inputStream; + fileOutputStream.write(values, 0, value4); + } + fileOutputStream.close(); + inputStream.close(); + Configuration.getInputOptions() + .processInputJar( + new InputJar( + ("" + text3 + name), ("" + text3 + name + ".obf"), text, jarEntry.getName())); + } + } + jarFile.close(); + } + + public boolean matchesText(String text) { + return text.length() > 0 && new File(text).isDirectory(); + } + + public String[] createTexts(String text) throws ConfigurationSaxException { + String text2 = text.substring("custom(".length(), text.length() - 1); + File file; + if (!(file = new File(text2)).isAbsolute()) { + try { + String text3; + if ((text3 = + new File(XmlParsingContext.getText(this.xmlParsingContext)) + .getCanonicalFile() + .getParent()) + != null) { + text2 = new File(("" + text3 + File.separator + text2)).getCanonicalPath(); + } + } catch (Exception exception) { + String text4; + if ((text4 = + new File(XmlParsingContext.getText(this.xmlParsingContext)) + .getAbsoluteFile() + .getParent()) + != null) { + text2 = new File(("" + text4 + File.separator + text2)).getAbsolutePath(); + } + } + file = new File(text2); + } + if (!file.exists()) { + throw new ConfigurationSaxException( + this.xmlParsingContext, + new StringBuilder() + .insert(0, "Cannot find file '") + .append(text2) + .append("'. ") + .append(this.createText()) + .toString()); + } + String[] texts; + try { + texts = FileUtils.createTexts(file, "UTF-8", true); + } catch (Exception exception2) { + throw new ConfigurationSaxException( + this.xmlParsingContext, + new StringBuilder() + .insert(0, exception2.getMessage()) + .append(" ") + .append(this.createText()) + .toString()); + } + if (texts != null && texts.length != 0) { + return texts; + } else { + throw new ConfigurationSaxException( + this.xmlParsingContext, + new StringBuilder() + .insert(0, "File '") + .append(text2) + .append("' is empty. ") + .append(this.createText()) + .toString()); + } + } + + public void processText4(String text) throws ConfigurationSaxException { + String text3 = text; + if (Configuration.getInputOptions().getValues3().size() == 0) { + throw new ConfigurationSaxException( + this.xmlParsingContext, + new StringBuilder() + .insert(0, "Cannot find parent jar. ") + .append(this.createText()) + .toString()); + } + InputEntry inputEntry = (InputEntry) Configuration.getInputOptions().getValues3().lastElement(); + if (text3.startsWith("/")) { + text3 = text3.substring(1); + } + try { + this.processText5(inputEntry.text2, text3); + } catch (Exception exception) { + throw new ConfigurationSaxException( + this.xmlParsingContext, + new StringBuilder() + .insert(0, exception.getMessage()) + .append(" ") + .append(this.createText()) + .toString()); + } + } + + @Override + public void setDocumentLocator(Locator locator2) { + if (locator2 != null) { + this.locator = locator2; + } + } + + public ConfigurationHandler(XmlParsingContext xmlParsingContext2) { + super(); + this.xmlParsingContext = xmlParsingContext2; + this.count = -1; + this.enabled2 = false; + this.text2 = ""; + this.text = ""; + this.locator = new ConfigurationLocator(this); + this.enabled = true; + } + + public ClassRule createClassRule( + String text, String text2, String text3, String text4, String text5) + throws ConfigurationSaxException { + String text6 = text; + this.processText(text6, text2); + byte value = 0; + byte value2 = 0; + if (text3 != null) { + if ("yes".equals(text3) || "true".equals(text3)) { + value = 1; + } else if ("keep-if-members-match".equals(text3)) { + value2 = 1; + } else if (!"no".equals(text3) && !"false".equals(text3)) { + this.processText("ignore", "true", "false", "yes", "no", "keep-if-members-match"); + } + } + boolean matches = false; + if ("yes".equals(text4) || "true".equals(text4)) { + matches = true; + } + byte value3 = 0; + if (text6 != null) { + if (text6.startsWith("!")) { + value3 = 1; + text6 = text6.substring(1).trim(); + } else if (text6.startsWith("not")) { + value3 = 1; + text6 = text6.substring(3).trim(); + } + } + try { + return new ClassRule( + this.createText(text6, text2, " class *"), + (value != 0), + matches, + (value2 != 0), + (value3 != 0)); + } catch (ConfigurationException configurationException) { + if (text6 != null) { + this.processText(text5); + } else { + this.processText("access"); + } + return null; + } + } + + public void processText( + String text, + String text2, + String text3, + String text4, + String text5, + String text6, + String text7, + String text8, + String text9) + throws ConfigurationSaxException { + throw new ConfigurationSaxException( + this.xmlParsingContext, + new StringBuilder() + .insert(0, "Attribute '") + .append(text) + .append("' should have one of the following values: '") + .append(text2) + .append("', '") + .append(text3) + .append("', '") + .append(text4) + .append("', '") + .append(text5) + .append("', '") + .append(text6) + .append("', '") + .append(text7) + .append("', '") + .append(text8) + .append("' or '") + .append(text9) + .append("'. ") + .append(this.createText()) + .toString()); + } + + public String createText() { + return new StringBuilder() + .insert(0, "[Line: ") + .append(this.locator.getLineNumber()) + .append("]") + .toString(); + } + + public void processText(String text, String text2, String text3) + throws ConfigurationSaxException { + throw new ConfigurationSaxException( + this.xmlParsingContext, + new StringBuilder() + .insert(0, "Attribute '") + .append(text) + .append("' should have one of the following values: '") + .append(text2) + .append("' or '") + .append(text3) + .append("'. ") + .append(this.createText()) + .toString()); + } +} diff --git a/src/main/java/com/allatori/config/ConfigurationLocator.java b/src/main/java/com/allatori/config/ConfigurationLocator.java new file mode 100644 index 0000000..22f05d9 --- /dev/null +++ b/src/main/java/com/allatori/config/ConfigurationLocator.java @@ -0,0 +1,33 @@ +package com.allatori.config; + +import org.xml.sax.Locator; + +public class ConfigurationLocator implements Locator { + + public final ConfigurationHandler configurationHandler; + + @Override + public int getLineNumber() { + return -1; + } + + @Override + public String getPublicId() { + return null; + } + + @Override + public int getColumnNumber() { + return -1; + } + + public ConfigurationLocator(ConfigurationHandler configurationHandler2) { + super(); + this.configurationHandler = configurationHandler2; + } + + @Override + public String getSystemId() { + return null; + } +} diff --git a/src/main/java/com/allatori/config/ConfigurationSaxException.java b/src/main/java/com/allatori/config/ConfigurationSaxException.java new file mode 100644 index 0000000..4043e21 --- /dev/null +++ b/src/main/java/com/allatori/config/ConfigurationSaxException.java @@ -0,0 +1,13 @@ +package com.allatori.config; + +import org.xml.sax.SAXException; + +public class ConfigurationSaxException extends SAXException { + + public final XmlParsingContext xmlParsingContext; + + public ConfigurationSaxException(XmlParsingContext xmlParsingContext2, String text) { + super(text); + this.xmlParsingContext = xmlParsingContext2; + } +} diff --git a/src/main/java/com/allatori/config/ConfigurationSource.java b/src/main/java/com/allatori/config/ConfigurationSource.java new file mode 100644 index 0000000..d95facb --- /dev/null +++ b/src/main/java/com/allatori/config/ConfigurationSource.java @@ -0,0 +1,6 @@ +package com.allatori.config; + +public interface ConfigurationSource { + + void parse() throws ConfigurationException; +} diff --git a/src/main/java/com/allatori/config/DebugInfoOptions.java b/src/main/java/com/allatori/config/DebugInfoOptions.java new file mode 100644 index 0000000..f089423 --- /dev/null +++ b/src/main/java/com/allatori/config/DebugInfoOptions.java @@ -0,0 +1,63 @@ +package com.allatori.config; + +import com.allatori.config.rule.RuleEntry; +import com.allatori.config.rule.RuleSet; +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.lib.bcel.generic.MethodGen; +import com.allatori.model.ClassStorage; + +public class DebugInfoOptions { + + public String text; + + public boolean enabled; + + public final Configuration configuration; + + public String text2; + + public RuleSet ruleSet; + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public void setText(String text) { + this.text = text; + } + + public boolean isEnabled() { + return this.enabled; + } + + public String getText() { + return this.text; + } + + public String getText2() { + return this.text2; + } + + public DebugInfoOptions(Configuration configuration2) { + super(); + this.configuration = configuration2; + this.ruleSet = new RuleSet(0); + } + + public boolean matchesMethodGen( + ClassStorage classStorage, ClassGen classGen, MethodGen methodGen) { + return this.ruleSet.calculateCount(classStorage, classGen, methodGen) == 1; + } + + public boolean matchesClassGen(ClassStorage classStorage, ClassGen classGen) { + return this.ruleSet.calculateCount(classStorage, classGen) == 1; + } + + public void setText2(String text2) { + this.text2 = text2; + } + + public void processRuleEntry(RuleEntry ruleEntry) { + this.ruleSet.processRuleEntry(ruleEntry); + } +} diff --git a/src/main/java/com/allatori/config/ExtensiveFlowOptions.java b/src/main/java/com/allatori/config/ExtensiveFlowOptions.java new file mode 100644 index 0000000..22eef08 --- /dev/null +++ b/src/main/java/com/allatori/config/ExtensiveFlowOptions.java @@ -0,0 +1,87 @@ +package com.allatori.config; + +import com.allatori.config.rule.RuleEntry; +import com.allatori.config.rule.RuleSet; +import com.allatori.lib.bcel.generic.AnnotationEntryGen; +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.lib.bcel.generic.ElementValuePairGen; +import com.allatori.lib.bcel.generic.MethodGen; +import com.allatori.model.ClassStorage; +import java.util.List; + +public class ExtensiveFlowOptions { + + public static final int COUNT = 0; + + public static final int COUNT2 = 2; + + public static final int COUNT3 = 1; + + public final Configuration configuration; + + public RuleSet ruleSet; + + public ExtensiveFlowOptions(Configuration configuration2) { + super(); + this.configuration = configuration2; + this.ruleSet = new RuleSet(1); + } + + public int calculateCount(ClassStorage classStorage, ClassGen classGen, MethodGen methodGen) { + if (!Configuration.getObfuscationOptions().isEnabled() + && methodGen.getName().startsWith("Allatori")) { + return 1; + } + byte value = 1; + AnnotationEntryGen[] annotationEntryGens = methodGen.getAnnotationEntryGens(); + while (true) { + AnnotationEntryGen[] annotationEntryGens2 = annotationEntryGens; + int value2 = annotationEntryGens2.length; + int value3; + for (int value4 = value3 = 0; value4 < value2; value4 = ++value3) { + AnnotationEntryGen annotationEntryGen = annotationEntryGens2[value3]; + if ("Lcom/allatori/annotations/DisableExtensiveFlowObfuscation;" + .equals(annotationEntryGen.getText2())) { + return 0; + } + if ("Lcom/allatori/annotations/NormalExtensiveFlowObfuscation;" + .equals(annotationEntryGen.getText2())) { + return 1; + } + if ("Lcom/allatori/annotations/MaximumExtensiveFlowObfuscation;" + .equals(annotationEntryGen.getText2())) { + return 2; + } + List values; + if ("Lcom/allatori/annotations/ExtensiveFlowObfuscation;" + .equals(annotationEntryGen.getText2()) + && (values = annotationEntryGen.getValues()) != null + && values.size() > 0 + && ((ElementValuePairGen) values.get(0)).getValue() != null) { + if ("maximum".equals(((ElementValuePairGen) values.get(0)).getValue().stringifyValue())) { + return 2; + } + if ("normal".equals(((ElementValuePairGen) values.get(0)).getValue().stringifyValue())) { + return 1; + } + if ("disable".equals(((ElementValuePairGen) values.get(0)).getValue().stringifyValue())) { + return 0; + } + } + } + if (value == 0) { + if (Configuration.getObfuscationOptions().isEnabled3() + && Configuration.getObfuscationOptions().isMethodsNamingEnabled()) { + return 0; + } + return this.ruleSet.calculateCount(classStorage, classGen, methodGen); + } + value = 0; + annotationEntryGens = classGen.getAnnotationEntries(); + } + } + + public void processRuleEntry(RuleEntry ruleEntry) { + this.ruleSet.processRuleEntry(ruleEntry); + } +} diff --git a/src/main/java/com/allatori/config/FieldRemovalOptions.java b/src/main/java/com/allatori/config/FieldRemovalOptions.java new file mode 100644 index 0000000..ceb5c4c --- /dev/null +++ b/src/main/java/com/allatori/config/FieldRemovalOptions.java @@ -0,0 +1,50 @@ +package com.allatori.config; + +import com.allatori.config.rule.RuleEntry; +import com.allatori.config.rule.RuleSet; +import com.allatori.lib.bcel.classfile.Field; +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.model.ClassStorage; +import java.util.Vector; + +public class FieldRemovalOptions { + + public Vector values; + + public final Configuration configuration; + + public RuleSet ruleSet; + + public boolean isValues() { + return this.values.size() > 0; + } + + public FieldRemovalOptions(Configuration configuration2) { + super(); + this.configuration = configuration2; + this.ruleSet = new RuleSet(0); + this.values = new Vector(); + } + + public void processText(String text) { + this.values.add(text); + } + + public boolean matchesText(String text) { + return this.values.contains(text); + } + + public boolean matchesField(ClassStorage classStorage, ClassGen classGen, Field field) { + if (classStorage == null) { + return false; + } else { + return this.ruleSet.getValues() == 0 + ? false + : this.ruleSet.calculateCount(classStorage, classGen, field) > 0; + } + } + + public void processRuleEntry(RuleEntry ruleEntry) { + this.ruleSet.processRuleEntry(ruleEntry); + } +} diff --git a/src/main/java/com/allatori/config/IgnoreClassesOptions.java b/src/main/java/com/allatori/config/IgnoreClassesOptions.java new file mode 100644 index 0000000..2d51628 --- /dev/null +++ b/src/main/java/com/allatori/config/IgnoreClassesOptions.java @@ -0,0 +1,45 @@ +package com.allatori.config; + +import com.allatori.config.rule.ClassRule; +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.model.ClassStorage; +import java.util.Iterator; +import java.util.Vector; + +public class IgnoreClassesOptions { + + public final Configuration configuration; + + public boolean enabled; + + public Vector values; + + public boolean matchesClassGen(ClassStorage classStorage, ClassGen classGen) { + if (!this.enabled) { + return false; + } + Iterator iterator2 = this.values.iterator(); + while (iterator2.hasNext()) { + ClassRule classRule; + if ((classRule = (ClassRule) iterator2.next()).matches(classStorage, classGen)) { + if (!classRule.matches()) { + return true; + } + return false; + } + } + return false; + } + + public void processClassRule(ClassRule classRule) { + this.values.add(classRule); + this.enabled = true; + } + + public IgnoreClassesOptions(Configuration configuration2) { + super(); + this.configuration = configuration2; + this.values = new Vector(); + this.enabled = false; + } +} diff --git a/src/main/java/com/allatori/config/InputEntry.java b/src/main/java/com/allatori/config/InputEntry.java new file mode 100644 index 0000000..237ff51 --- /dev/null +++ b/src/main/java/com/allatori/config/InputEntry.java @@ -0,0 +1,14 @@ +package com.allatori.config; + +public class InputEntry { + + public String text; + + public String text2; + + public InputEntry(String text2, String text) { + super(); + this.text2 = text2; + this.text = text; + } +} diff --git a/src/main/java/com/allatori/config/InputJar.java b/src/main/java/com/allatori/config/InputJar.java new file mode 100644 index 0000000..88fd7ee --- /dev/null +++ b/src/main/java/com/allatori/config/InputJar.java @@ -0,0 +1,14 @@ +package com.allatori.config; + +public class InputJar extends InputEntry { + + public String text; + + public String text2; + + public InputJar(String text3, String text4, String text, String text2) { + super(text3, text4); + this.text = text; + this.text2 = text2; + } +} diff --git a/src/main/java/com/allatori/config/InputOptions.java b/src/main/java/com/allatori/config/InputOptions.java new file mode 100644 index 0000000..18553ea --- /dev/null +++ b/src/main/java/com/allatori/config/InputOptions.java @@ -0,0 +1,57 @@ +package com.allatori.config; + +import java.util.Vector; + +public class InputOptions { + + public final Configuration configuration; + + public Vector values; + + public Vector values2; + + public Vector values3; + + public String text; + + public void setText(String text) { + this.text = text; + } + + public void processInputJar(InputJar inputJar) { + this.values.add(inputJar); + } + + public String getText() { + return this.text; + } + + public Vector getValues() { + return this.values; + } + + public Vector getValues3() { + return this.values3; + } + + public InputOptions(Configuration configuration2) { + super(); + this.configuration = configuration2; + this.values3 = new Vector(); + this.values = new Vector(); + this.values2 = new Vector(); + this.text = null; + } + + public void processInputEntry(InputEntry inputEntry) { + this.values3.add(inputEntry); + } + + public void processClassPathEntry(ClassPathEntry classPathEntry) { + this.values2.add(classPathEntry); + } + + public Vector getValues2() { + return this.values2; + } +} diff --git a/src/main/java/com/allatori/config/KeepNamesOptions.java b/src/main/java/com/allatori/config/KeepNamesOptions.java new file mode 100644 index 0000000..1a3e8a0 --- /dev/null +++ b/src/main/java/com/allatori/config/KeepNamesOptions.java @@ -0,0 +1,200 @@ +package com.allatori.config; + +import com.allatori.config.rule.ClassRule; +import com.allatori.config.rule.FieldRule; +import com.allatori.config.rule.MethodRule; +import com.allatori.lib.bcel.classfile.AnnotationEntry; +import com.allatori.lib.bcel.classfile.Field; +import com.allatori.lib.bcel.classfile.Method; +import com.allatori.lib.bcel.generic.AnnotationEntryGen; +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.model.ClassStorage; +import java.util.Vector; + +public class KeepNamesOptions { + + public final RenamingOptions renamingOptions; + + public Vector values; + + public ClassRule classRule; + + public boolean matchesMethod(ClassStorage classStorage, ClassGen classGen, Method method) { + if (this.matchesMethod2(classStorage, classGen, method)) { + return true; + } + if (RenamingOptions.matchesRenamingOptions(this.renamingOptions)) { + return false; + } + AnnotationEntry[] annotationEntries = method.getAnnotationEntries(); + int value; + for (int value2 = value = 0; value2 < annotationEntries.length; value2 = ++value) { + AnnotationEntry annotationEntry = annotationEntries[value]; + if ("Lcom/allatori/annotations/Rename;".equals(annotationEntry.getText())) { + return true; + } + if ("Lcom/allatori/annotations/DoNotRename;".equals(annotationEntry.getText())) { + return false; + } + if ("Lcom/allatori/annotations/KeepName;".equals(annotationEntry.getText())) { + return false; + } + } + int value3; + for (int value4 = value3 = 0; value4 < this.values.size(); value4 = ++value3) { + ClassRule classRule2; + if ((classRule2 = (ClassRule) this.values.get(value3)).matches5() + && classRule2.matches(classStorage, classGen) + && classRule2.matches(method)) { + return false; + } + if (classRule2.matches() && classRule2.matches(classStorage, classGen)) { + return true; + } + } + return !this.classRule.matches5() || !this.classRule.matches(method); + } + + public boolean matchesMethod2(ClassStorage classStorage, ClassGen classGen, Method method) { + return method.getText().startsWith("Allatori") || this.matchesClassGen2(classStorage, classGen); + } + + public void processFieldRule(FieldRule fieldRule) { + this.classRule.processFieldRule(fieldRule); + } + + public KeepNamesOptions( + RenamingOptions renamingOptions, + NamingOptionsConstructorToken namingOptionsConstructorToken) { + this(renamingOptions); + } + + public boolean matchesField(ClassStorage classStorage, ClassGen classGen, Field field) { + if (this.matchesField2(classStorage, classGen, field)) { + return true; + } + if (RenamingOptions.matchesRenamingOptions(this.renamingOptions)) { + return false; + } + AnnotationEntry[] annotationEntries = field.getAnnotationEntries(); + int value; + for (int value2 = value = 0; value2 < annotationEntries.length; value2 = ++value) { + AnnotationEntry annotationEntry = annotationEntries[value]; + if ("Lcom/allatori/annotations/Rename;".equals(annotationEntry.getText())) { + return true; + } + if ("Lcom/allatori/annotations/DoNotRename;".equals(annotationEntry.getText())) { + return false; + } + if ("Lcom/allatori/annotations/KeepName;".equals(annotationEntry.getText())) { + return false; + } + } + int value3; + for (int value4 = value3 = 0; value4 < this.values.size(); value4 = ++value3) { + ClassRule classRule2; + if ((classRule2 = (ClassRule) this.values.get(value3)).matches4() + && classRule2.matches(classStorage, classGen) + && classRule2.matches(classStorage, field)) { + return false; + } + if (classRule2.matches() && classRule2.matches(classStorage, classGen)) { + return true; + } + } + return !this.classRule.matches4() || !this.classRule.matches(classStorage, field); + } + + public boolean matchesField2(ClassStorage classStorage, ClassGen classGen, Field field) { + return this.matchesClassGen2(classStorage, classGen); + } + + public boolean matchesClassGen(ClassStorage classStorage, ClassGen classGen) { + if (this.matchesClassGen2(classStorage, classGen)) { + return true; + } + if (RenamingOptions.matchesRenamingOptions(this.renamingOptions)) { + return false; + } + AnnotationEntryGen[] annotationEntries = classGen.getAnnotationEntries(); + int value; + for (int value2 = value = 0; value2 < annotationEntries.length; value2 = ++value) { + AnnotationEntryGen annotationEntryGen = annotationEntries[value]; + if ("Lcom/allatori/annotations/Rename;".equals(annotationEntryGen.getText2())) { + return true; + } + if ("Lcom/allatori/annotations/DoNotRename;".equals(annotationEntryGen.getText2())) { + return false; + } + if ("Lcom/allatori/annotations/KeepName;".equals(annotationEntryGen.getText2())) { + return false; + } + } + int value3; + for (int value4 = value3 = 0; value4 < this.values.size(); value4 = ++value3) { + ClassRule classRule; + if ((!(classRule = (ClassRule) this.values.get(value3)).matches2() || classRule.matches()) + && classRule.matches(classStorage, classGen)) { + if (classRule.matches()) { + return true; + } + if (!classRule.matches3()) { + return false; + } + int value5; + Field[] fields; + for (int value6 = value5 = (fields = classGen.getFields()).length - 1; + value6 >= 0; + value6 = --value5) { + Field field = fields[value5]; + if (!Configuration.getRenamingOptions() + .getKeepNamesOptions() + .matchesField(classStorage, classGen, field)) { + return false; + } + } + int value7; + Method[] methods; + for (int value8 = value7 = (methods = classGen.getMethods()).length - 1; + value8 >= 0; + value8 = --value7) { + Method method = methods[value7]; + if (!Configuration.getRenamingOptions() + .getKeepNamesOptions() + .matchesMethod(classStorage, classGen, method)) { + return false; + } + } + } + } + return true; + } + + public void processClassRule(ClassRule classRule) { + this.values.add(classRule); + } + + public KeepNamesOptions(RenamingOptions renamingOptions2) { + super(); + this.renamingOptions = renamingOptions2; + this.values = new Vector(); + try { + this.classRule = new ClassRule("class *", true, false); + ClassRule classRule2 = new ClassRule("class * extends java.lang.Enum", true, false); + classRule2.processMethodRule(new MethodRule("values(**)", false, false)); + classRule2.processMethodRule(new MethodRule("valueOf(**)", false, false)); + this.processClassRule(classRule2); + this.processClassRule(new ClassRule("interface *.package-info", false, false)); + } catch (ConfigurationException configurationException) { + configurationException.printStackTrace(); + } + } + + public void processMethodRule(MethodRule methodRule) { + this.classRule.processMethodRule(methodRule); + } + + public boolean matchesClassGen2(ClassStorage classStorage, ClassGen classGen) { + return classStorage.getInputClasses().contains(classGen); + } +} diff --git a/src/main/java/com/allatori/config/LineNumberOptions.java b/src/main/java/com/allatori/config/LineNumberOptions.java new file mode 100644 index 0000000..afb2eb5 --- /dev/null +++ b/src/main/java/com/allatori/config/LineNumberOptions.java @@ -0,0 +1,28 @@ +package com.allatori.config; + +public class LineNumberOptions { + + public static final int COUNT = 3; + + public final RenamingOptions renamingOptions; + + public int lineNumbersMode; + + public static final int COUNT2 = 2; + + public static final int COUNT3 = 1; + + public void setLineNumbersMode(int lineNumbersMode) { + this.lineNumbersMode = lineNumbersMode; + } + + public int getLineNumbersMode() { + return this.lineNumbersMode; + } + + public LineNumberOptions(RenamingOptions renamingOptions2) { + super(); + this.renamingOptions = renamingOptions2; + this.lineNumbersMode = 1; + } +} diff --git a/src/main/java/com/allatori/config/LocalVariableOptions.java b/src/main/java/com/allatori/config/LocalVariableOptions.java new file mode 100644 index 0000000..6ec2fc7 --- /dev/null +++ b/src/main/java/com/allatori/config/LocalVariableOptions.java @@ -0,0 +1,76 @@ +package com.allatori.config; + +import com.allatori.config.rule.RuleEntry; +import com.allatori.config.rule.RuleSet; +import com.allatori.lib.bcel.classfile.Method; +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.lib.bcel.generic.MethodGen; +import com.allatori.model.ClassStorage; + +public class LocalVariableOptions { + + public RuleSet ruleSet; + + public static final int COUNT = 4; + + public static final int COUNT2 = 5; + + public final RenamingOptions renamingOptions; + + public static final int COUNT3 = 3; + + public static final int COUNT4 = 1; + + public static final int COUNT5 = 6; + + public String localVariablesNaming; + + public static final int COUNT6 = 2; + + public int localVariablesNamingMode; + + public void setLocalVariablesNaming(String localVariablesNaming) { + this.localVariablesNaming = localVariablesNaming; + } + + public void processRuleEntry(RuleEntry ruleEntry) { + this.ruleSet.processRuleEntry(ruleEntry); + } + + public int calculateCount(ClassStorage classStorage, ClassGen classGen, MethodGen methodGen) { + return Configuration.getObfuscationOptions().isEnabled3() + && Configuration.getObfuscationOptions().isMethodsNamingEnabled() + ? 4 + : this.ruleSet.calculateCount(classStorage, classGen, methodGen); + } + + public void setLocalVariablesNamingMode(int localVariablesNamingMode) { + this.localVariablesNamingMode = localVariablesNamingMode; + } + + public int calculateCount(ClassStorage classStorage, ClassGen classGen, Method method) { + return Configuration.getObfuscationOptions().isEnabled3() + && Configuration.getObfuscationOptions().isMethodsNamingEnabled() + ? 4 + : this.ruleSet.calculateCount(classStorage, classGen, method); + } + + public LocalVariableOptions(RenamingOptions renamingOptions2) { + super(); + this.renamingOptions = renamingOptions2; + this.localVariablesNamingMode = 6; + this.ruleSet = new RuleSet(6); + this.localVariablesNaming = "a"; + } + + public String getLocalVariablesNaming() { + return this.localVariablesNaming; + } + + public int calculateCount() { + return Configuration.getObfuscationOptions().isEnabled3() + && Configuration.getObfuscationOptions().isMethodsNamingEnabled() + ? 4 + : this.localVariablesNamingMode; + } +} diff --git a/src/main/java/com/allatori/config/LogOptions.java b/src/main/java/com/allatori/config/LogOptions.java new file mode 100644 index 0000000..99c74e9 --- /dev/null +++ b/src/main/java/com/allatori/config/LogOptions.java @@ -0,0 +1,26 @@ +package com.allatori.config; + +public class LogOptions { + + public String comLicense4jSupport; + + public final Configuration configuration; + + public void setComLicense4jSupport(String comLicense4jSupport) { + this.comLicense4jSupport = comLicense4jSupport; + } + + public boolean isText() { + return this.comLicense4jSupport != null; + } + + public LogOptions(Configuration configuration2) { + super(); + this.configuration = configuration2; + this.comLicense4jSupport = null; + } + + public String getComLicense4jSupport() { + return this.comLicense4jSupport; + } +} diff --git a/src/main/java/com/allatori/config/MappingOptions.java b/src/main/java/com/allatori/config/MappingOptions.java new file mode 100644 index 0000000..25bc7da --- /dev/null +++ b/src/main/java/com/allatori/config/MappingOptions.java @@ -0,0 +1,20 @@ +package com.allatori.config; + +import com.allatori.naming.RenamingLog; +import com.allatori.util.LookupTable; + +public class MappingOptions { + + public LookupTable lookupTable; + + public RenamingLog renamingLog; + + public final Configuration configuration; + + public LookupTable lookupTable2; + + public MappingOptions(Configuration configuration2) { + super(); + this.configuration = configuration2; + } +} diff --git a/src/main/java/com/allatori/config/MemberOrderOptions.java b/src/main/java/com/allatori/config/MemberOrderOptions.java new file mode 100644 index 0000000..48b3589 --- /dev/null +++ b/src/main/java/com/allatori/config/MemberOrderOptions.java @@ -0,0 +1,44 @@ +package com.allatori.config; + +import com.allatori.config.rule.RuleEntry; +import com.allatori.config.rule.RuleSet; +import com.allatori.lib.bcel.classfile.Field; +import com.allatori.lib.bcel.classfile.Method; +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.model.ClassStorage; + +public class MemberOrderOptions { + + public final Configuration configuration; + + public RuleSet ruleSet; + + public RuleSet ruleSet2; + + public void processRuleEntry(RuleEntry ruleEntry) { + this.ruleSet2.processRuleEntry(ruleEntry); + } + + public boolean matchesMethod(ClassStorage classStorage, ClassGen classGen, Method method) { + return classStorage == null || this.ruleSet.getValues() == 0 + ? false + : this.ruleSet.calculateCount(classStorage, classGen, method) > 0; + } + + public boolean matchesField(ClassStorage classStorage, ClassGen classGen, Field field) { + return classStorage == null || this.ruleSet2.getValues() == 0 + ? false + : this.ruleSet2.calculateCount(classStorage, classGen, field) > 0; + } + + public void processRuleEntry2(RuleEntry ruleEntry) { + this.ruleSet.processRuleEntry(ruleEntry); + } + + public MemberOrderOptions(Configuration configuration2) { + super(); + this.configuration = configuration2; + this.ruleSet2 = new RuleSet(0); + this.ruleSet = new RuleSet(0); + } +} diff --git a/src/main/java/com/allatori/config/MethodCallRemovalOptions.java b/src/main/java/com/allatori/config/MethodCallRemovalOptions.java new file mode 100644 index 0000000..e5d17f1 --- /dev/null +++ b/src/main/java/com/allatori/config/MethodCallRemovalOptions.java @@ -0,0 +1,73 @@ +package com.allatori.config; + +import com.allatori.config.rule.RuleEntry; +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.lib.bcel.generic.MethodGen; +import com.allatori.model.ClassStorage; +import com.allatori.transform.DistributedStringEncryptionTransformer; +import java.util.Iterator; +import java.util.Vector; + +public class MethodCallRemovalOptions { + + public Vector values; + + public boolean enabled; + + public final Configuration configuration; + + public boolean isEnabled() { + return this.enabled; + } + + public MethodCallRemovalOptions(Configuration configuration2) { + super(); + this.configuration = configuration2; + this.enabled = false; + this.values = new Vector(); + } + + public boolean matchesText( + ClassStorage classStorage, + ClassGen classGen, + MethodGen methodGen, + String text3, + String text5, + String text6) { + if (classStorage != null && text3 != null && text5 != null) { + if (text5.startsWith(DistributedStringEncryptionTransformer.text4)) { + return false; + } + if ("".equals(text5)) { + return false; + } + if ("".equals(text5)) { + return false; + } + if (this.values.size() == 0) { + return false; + } + Iterator iterator2 = this.values.iterator(); + while (iterator2.hasNext()) { + MethodCallRemovalRule methodCallRemovalRule; + if ((methodCallRemovalRule = (MethodCallRemovalRule) iterator2.next()) + .ruleEntry.classRule.matches(classStorage, classGen) + && methodCallRemovalRule.ruleEntry.classRule.matches(methodGen) + && text3.matches(methodCallRemovalRule.text) + && text5.matches(methodCallRemovalRule.text2)) { + return true; + } + } + return Configuration.getOptimizationOptions().matchesText("" + text3 + "." + text5 + text6); + } else { + return false; + } + } + + public void processText(RuleEntry ruleEntry, String text, String text2) { + this.enabled = true; + String text3 = text.replaceAll("\\.", "\\\\.").replaceAll("\\*", ".*"); + String text4 = text2.replaceAll("\\.", "\\\\.").replaceAll("\\*", ".*"); + this.values.add(new MethodCallRemovalRule(this, ruleEntry, text3, text4)); + } +} diff --git a/src/main/java/com/allatori/config/MethodCallRemovalRule.java b/src/main/java/com/allatori/config/MethodCallRemovalRule.java new file mode 100644 index 0000000..22fe477 --- /dev/null +++ b/src/main/java/com/allatori/config/MethodCallRemovalRule.java @@ -0,0 +1,26 @@ +package com.allatori.config; + +import com.allatori.config.rule.RuleEntry; + +public class MethodCallRemovalRule { + + public String text; + + public RuleEntry ruleEntry; + + public final MethodCallRemovalOptions methodCallRemovalOptions; + + public String text2; + + public MethodCallRemovalRule( + MethodCallRemovalOptions methodCallRemovalOptions2, + RuleEntry ruleEntry2, + String text, + String text2) { + super(); + this.methodCallRemovalOptions = methodCallRemovalOptions2; + this.ruleEntry = ruleEntry2; + this.text = text; + this.text2 = text2; + } +} diff --git a/src/main/java/com/allatori/config/MethodRemovalOptions.java b/src/main/java/com/allatori/config/MethodRemovalOptions.java new file mode 100644 index 0000000..5c61c82 --- /dev/null +++ b/src/main/java/com/allatori/config/MethodRemovalOptions.java @@ -0,0 +1,45 @@ +package com.allatori.config; + +import com.allatori.config.rule.RuleEntry; +import com.allatori.config.rule.RuleSet; +import com.allatori.lib.bcel.classfile.Method; +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.model.ClassStorage; + +public class MethodRemovalOptions { + + public String testString; + + public RuleSet ruleSet; + + public final Configuration configuration; + + public void setTestString(String testString) { + this.testString = testString; + } + + public void processRuleEntry(RuleEntry ruleEntry) { + this.ruleSet.processRuleEntry(ruleEntry); + } + + public MethodRemovalOptions(Configuration configuration2) { + super(); + this.configuration = configuration2; + this.ruleSet = new RuleSet(0); + this.testString = null; + } + + public String getTestString() { + return this.testString; + } + + public boolean matchesMethod(ClassStorage classStorage, ClassGen classGen, Method method) { + if (classStorage == null) { + return false; + } else { + return this.ruleSet.getValues() == 0 + ? false + : this.ruleSet.calculateCount(classStorage, classGen, method) > 0; + } + } +} diff --git a/src/main/java/com/allatori/config/NameGenerationOptions.java b/src/main/java/com/allatori/config/NameGenerationOptions.java new file mode 100644 index 0000000..cd73ac2 --- /dev/null +++ b/src/main/java/com/allatori/config/NameGenerationOptions.java @@ -0,0 +1,346 @@ +package com.allatori.config; + +import com.allatori.naming.generator.AsciiNameGenerator; +import com.allatori.naming.generator.JavaKeywordNameGenerator; +import com.allatori.naming.generator.LengthBoundNameGenerator; +import com.allatori.naming.generator.LowercaseConfusableNameGenerator; +import com.allatori.naming.generator.LowercaseNameGenerator; +import com.allatori.naming.generator.MainNameGenerator; +import com.allatori.naming.generator.MethodNameGenerator; +import com.allatori.naming.generator.MixedConfusableNameGenerator; +import com.allatori.naming.generator.NameGenerator; +import com.allatori.naming.generator.NumericNameGenerator; +import com.allatori.naming.generator.PackageNameGenerator; +import com.allatori.naming.generator.PrefixedNameGenerator; +import com.allatori.naming.generator.RandomizedNameGenerator; +import com.allatori.naming.generator.TypeNameGenerator; +import com.allatori.naming.generator.UppercaseNameGenerator; +import com.allatori.naming.generator.WindowsDeviceNameGenerator; +import java.util.Locale; + +public class NameGenerationOptions { + + public String[] texts; + + public static final int COUNT = 3; + + public static final int COUNT2 = 1; + + public static final int COUNT3 = 9; + + public String[] texts2; + + public static final int COUNT4 = 4; + + public String methodsNamingPrefix; + + public static final int COUNT5 = 8; + + public String text2; + + public String[] texts3; + + public int classesNamingMode; + + public final RenamingOptions renamingOptions; + + public static final int COUNT6 = 2; + + public String classesNamingPrefix; + + public String[] texts4; + + public static final int COUNT7 = 6; + + public String fieldsNamingPrefix; + + public int packagesNamingMode; + + public int methodsNamingMode; + + public int fieldsNamingMode; + + public boolean fieldsNamingEnabled; + + public boolean classesNamingEnabled; + + public static final int COUNT8 = 5; + + public boolean methodsNamingEnabled; + + public static final int COUNT9 = 7; + + public void setTexts3(String[] texts) { + this.texts3 = texts; + } + + public void setMethodsNamingPrefix(String methodsNamingPrefix) { + this.methodsNamingPrefix = methodsNamingPrefix; + } + + public NameGenerator createNameGenerator() { + return new LengthBoundNameGenerator(new LowercaseNameGenerator()); + } + + public void setEnabled(boolean fieldsNamingEnabled) { + this.fieldsNamingEnabled = fieldsNamingEnabled; + } + + public void setTexts(String[] texts2) { + this.texts = texts2; + } + + public String getText() { + if (this.methodsNamingMode == 5) { + return MixedConfusableNameGenerator.nextName2(); + } else { + return this.methodsNamingMode == 9 + ? LowercaseConfusableNameGenerator.nextName2() + : RenamingOptions.getLocalVariableOptions(this.renamingOptions).getLocalVariablesNaming(); + } + } + + public NameGenerator createNameGenerator2() { + NameGenerator nameGenerator; + NameGenerationOptions nameGenerationOptions; + if (this.methodsNamingMode == 1) { + nameGenerator = new LowercaseNameGenerator(); + nameGenerationOptions = this; + } else if (this.methodsNamingMode == 8) { + nameGenerator = new UppercaseNameGenerator(); + nameGenerationOptions = this; + } else if (this.methodsNamingMode == 3) { + nameGenerator = new JavaKeywordNameGenerator(); + nameGenerationOptions = this; + } else if (this.methodsNamingMode == 5) { + nameGenerator = new MixedConfusableNameGenerator(); + nameGenerationOptions = this; + } else if (this.methodsNamingMode == 9) { + nameGenerator = new LowercaseConfusableNameGenerator(); + nameGenerationOptions = this; + } else if (this.methodsNamingMode == 6) { + nameGenerator = new NumericNameGenerator(); + nameGenerationOptions = this; + } else if (this.methodsNamingMode == 7) { + nameGenerator = new PackageNameGenerator(this.texts); + nameGenerationOptions = this; + } else { + nameGenerator = new AsciiNameGenerator(); + nameGenerationOptions = this; + } + if (nameGenerationOptions.methodsNamingEnabled) { + nameGenerator = new MainNameGenerator(nameGenerator, false, true); + } + NameGenerator nameGenerator2 = new LengthBoundNameGenerator(nameGenerator); + if (this.text2 != null) { + nameGenerator2 = new MethodNameGenerator(this.text2, nameGenerator2); + } + if (this.methodsNamingPrefix != null) { + nameGenerator2 = new TypeNameGenerator(this.methodsNamingPrefix, nameGenerator2); + } + return nameGenerator2; + } + + public NameGenerator createNameGenerator3() { + if (RenamingOptions.getLocalVariableOptions(this.renamingOptions).calculateCount() == 2) { + return new LowercaseNameGenerator(); + } else { + return RenamingOptions.getLocalVariableOptions(this.renamingOptions).calculateCount() == 1 + ? new PrefixedNameGenerator( + RenamingOptions.getLocalVariableOptions(this.renamingOptions) + .getLocalVariablesNaming()) + : new LowercaseNameGenerator(); + } + } + + public NameGenerator createNameGenerator4() { + NameGenerator nameGenerator; + if (this.packagesNamingMode == 6) { + nameGenerator = new NumericNameGenerator(); + } else if (this.packagesNamingMode == 7) { + nameGenerator = new PackageNameGenerator(this.texts4); + } else if (this.packagesNamingMode == 8) { + nameGenerator = new UppercaseNameGenerator(); + } else { + nameGenerator = new LowercaseNameGenerator(); + } + return new LengthBoundNameGenerator(nameGenerator); + } + + public NameGenerationOptions(RenamingOptions renamingOptions2) { + super(); + this.renamingOptions = renamingOptions2; + this.packagesNamingMode = 1; + this.classesNamingMode = 2; + this.classesNamingEnabled = false; + this.fieldsNamingMode = 2; + this.methodsNamingMode = 2; + this.fieldsNamingEnabled = false; + this.methodsNamingEnabled = false; + this.text2 = null; + this.fieldsNamingPrefix = null; + this.methodsNamingPrefix = null; + this.classesNamingPrefix = null; + this.texts2 = null; + this.texts = null; + this.texts3 = null; + this.texts4 = null; + } + + public boolean isClassesNamingEnabled() { + return this.classesNamingEnabled; + } + + public void setMethodsNamingMode(int methodsNamingMode) { + this.methodsNamingMode = methodsNamingMode; + } + + public void setFieldsNamingMode(int fieldsNamingMode) { + this.fieldsNamingMode = fieldsNamingMode; + } + + public boolean isFieldsNamingEnabled() { + return this.fieldsNamingEnabled; + } + + public void setClassesNamingPrefix(String classesNamingPrefix) { + this.classesNamingPrefix = classesNamingPrefix; + } + + public NameGenerator createNameGenerator5() { + NameGenerator nameGenerator; + NameGenerationOptions nameGenerationOptions; + if (this.fieldsNamingMode == 1) { + nameGenerator = new LowercaseNameGenerator(); + nameGenerationOptions = this; + } else if (this.fieldsNamingMode == 8) { + nameGenerator = new UppercaseNameGenerator(); + nameGenerationOptions = this; + } else if (this.fieldsNamingMode == 3) { + nameGenerator = new JavaKeywordNameGenerator(); + nameGenerationOptions = this; + } else if (this.fieldsNamingMode == 5) { + nameGenerator = new MixedConfusableNameGenerator(); + nameGenerationOptions = this; + } else if (this.fieldsNamingMode == 9) { + nameGenerator = new LowercaseConfusableNameGenerator(); + nameGenerationOptions = this; + } else if (this.fieldsNamingMode == 6) { + nameGenerator = new NumericNameGenerator(); + nameGenerationOptions = this; + } else if (this.fieldsNamingMode == 7) { + nameGenerator = new PackageNameGenerator(this.texts2); + nameGenerationOptions = this; + } else { + nameGenerator = new AsciiNameGenerator(); + nameGenerationOptions = this; + } + if (nameGenerationOptions.fieldsNamingEnabled) { + nameGenerator = new MainNameGenerator(nameGenerator, true, false); + } + NameGenerator nameGenerator2 = new LengthBoundNameGenerator(nameGenerator); + if (this.text2 != null) { + nameGenerator2 = new MethodNameGenerator(this.text2, nameGenerator2); + } + if (this.fieldsNamingPrefix != null) { + nameGenerator2 = new TypeNameGenerator(this.fieldsNamingPrefix, nameGenerator2); + } + return nameGenerator2; + } + + public void setTexts4(String[] texts) { + this.texts4 = texts; + } + + public void setEnabled3(boolean methodsNamingEnabled) { + this.methodsNamingEnabled = methodsNamingEnabled; + } + + public NameGenerator createNameGenerator6() { + NameGenerator nameGenerator; + NameGenerationOptions nameGenerationOptions; + if (this.classesNamingMode == 1) { + nameGenerator = new LowercaseNameGenerator(); + nameGenerationOptions = this; + } else if (this.classesNamingMode == 8) { + nameGenerator = new UppercaseNameGenerator(); + nameGenerationOptions = this; + } else if (this.classesNamingMode == 4) { + nameGenerator = new WindowsDeviceNameGenerator(); + nameGenerationOptions = this; + } else if (this.classesNamingMode == 5) { + nameGenerator = new MixedConfusableNameGenerator(); + nameGenerationOptions = this; + } else if (this.classesNamingMode == 9) { + nameGenerator = new LowercaseConfusableNameGenerator(); + nameGenerationOptions = this; + } else if (this.classesNamingMode == 6) { + nameGenerator = new NumericNameGenerator(); + nameGenerationOptions = this; + } else if (this.classesNamingMode == 7) { + nameGenerator = new PackageNameGenerator(this.texts3); + nameGenerationOptions = this; + } else { + nameGenerator = new AsciiNameGenerator(); + nameGenerationOptions = this; + } + String text; + if (nameGenerationOptions.classesNamingMode != 1 + && this.classesNamingMode != 8 + && this.classesNamingMode != 6 + && this.classesNamingMode != 9 + && this.classesNamingMode != 7 + && Configuration.getInputOptions().getValues2().size() > 0 + && ((text = System.getProperty("os.name").toLowerCase(Locale.ENGLISH)) == null + || text.indexOf("win") >= 0 + || text.indexOf("mac") >= 0)) { + nameGenerator = new LowercaseNameGenerator(); + } + if (Configuration.getObfuscationOptions().isEnabled3()) { + nameGenerator = new RandomizedNameGenerator(nameGenerator); + } + NameGenerator nameGenerator2 = new LengthBoundNameGenerator(nameGenerator); + if (this.classesNamingPrefix != null) { + nameGenerator2 = new TypeNameGenerator(this.classesNamingPrefix, nameGenerator2); + } + return nameGenerator2; + } + + public void setEnabled2(boolean classesNamingEnabled) { + this.classesNamingEnabled = classesNamingEnabled; + } + + public NameGenerationOptions( + RenamingOptions renamingOptions, + NamingOptionsConstructorToken namingOptionsConstructorToken) { + this(renamingOptions); + } + + public void setTexts2(String[] texts) { + this.texts2 = texts; + } + + public void processText(String text2) { + if (this.text2 == null) { + this.text2 = text2; + } else { + this.text2 = "" + this.text2 + this.text2.substring(8, 9) + text2; + } + } + + public void setFieldsNamingPrefix(String fieldsNamingPrefix) { + this.fieldsNamingPrefix = fieldsNamingPrefix; + } + + public void setClassesNamingMode(int classesNamingMode) { + this.classesNamingMode = classesNamingMode; + } + + public boolean isMethodsNamingEnabled() { + return this.methodsNamingEnabled; + } + + public void setPackagesNamingMode(int packagesNamingMode) { + this.packagesNamingMode = packagesNamingMode; + } +} diff --git a/src/main/java/com/allatori/config/NamingOptionsConstructorToken.java b/src/main/java/com/allatori/config/NamingOptionsConstructorToken.java new file mode 100644 index 0000000..e8dd0b8 --- /dev/null +++ b/src/main/java/com/allatori/config/NamingOptionsConstructorToken.java @@ -0,0 +1,3 @@ +package com.allatori.config; + +public class NamingOptionsConstructorToken {} diff --git a/src/main/java/com/allatori/config/ObfuscationOptions.java b/src/main/java/com/allatori/config/ObfuscationOptions.java new file mode 100644 index 0000000..9c03ed2 --- /dev/null +++ b/src/main/java/com/allatori/config/ObfuscationOptions.java @@ -0,0 +1,426 @@ +package com.allatori.config; + +import com.allatori.config.rule.RuleEntry; +import com.allatori.config.rule.RuleSet; +import com.allatori.lib.bcel.classfile.Method; +import com.allatori.lib.bcel.generic.AnnotationEntryGen; +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.lib.bcel.generic.ElementValuePairGen; +import com.allatori.lib.bcel.generic.MethodGen; +import com.allatori.model.ClassStorage; +import java.util.Hashtable; +import java.util.List; + +public class ObfuscationOptions { + + public RuleSet ruleSet; + + public static final int COUNT = 1; + + public char stringEncryptionSeed; + + public boolean enabled; + + public static final int COUNT2 = 2; + + public static final int COUNT3 = 1; + + public RuleSet ruleSet2; + + public boolean outputJarCommentEnabled; + + public String decryptorExcludePattern; + + public boolean enabled3; + + public static final int COUNT4 = 0; + + public RuleSet ruleSet3; + + public static final int COUNT5 = 100; + + public static final int COUNT6 = 0; + + public boolean java6Enabled; + + public String stringEncryptionIgnoredStrings; + + public boolean packageStringEncryptionEnabled; + + public Hashtable entries; + + public String decryptorIncludePattern; + + public static final int COUNT7 = 0; + + public RuleSet ruleSet4; + + public String randomSeed; + + public String outputJarComment; + + public boolean methodsNamingEnabled; + + public boolean globalStringEncryptionEnabled; + + public String text6; + + public int stringEncryptionVersion; + + public static final int COUNT8 = 1000; + + public static final int COUNT9 = 3; + + public final Configuration configuration; + + public static final int COUNT10 = 1; + + public RuleSet ruleSet5; + + public static final int COUNT11 = 0; + + public static final int COUNT12 = 101; + + public static final int COUNT13 = 1; + + public RuleSet ruleSet6; + + public boolean finalizeEnabled; + + public RuleSet ruleSet7; + + public void setDecryptorExcludePattern(String decryptorExcludePattern) { + this.decryptorExcludePattern = decryptorExcludePattern; + } + + public void setEnabled7(boolean globalStringEncryptionEnabled) { + this.globalStringEncryptionEnabled = globalStringEncryptionEnabled; + } + + public void setCharacter(char stringEncryptionSeed) { + this.stringEncryptionSeed = stringEncryptionSeed; + } + + public boolean isOutputJarCommentEnabled() { + return this.outputJarCommentEnabled; + } + + public String getRandomSeed() { + return this.randomSeed; + } + + public void setEnabled3(boolean enabled3) { + this.enabled3 = enabled3; + } + + public ObfuscationOptions(Configuration configuration2) { + super(); + this.configuration = configuration2; + this.entries = new Hashtable(); + this.ruleSet6 = new RuleSet(1); + this.ruleSet5 = new RuleSet(0); + this.ruleSet3 = new RuleSet(1); + this.ruleSet = new RuleSet(1); + this.ruleSet7 = new RuleSet(0); + this.ruleSet2 = new RuleSet(0); + this.ruleSet4 = new RuleSet(0); + this.randomSeed = null; + this.finalizeEnabled = false; + this.enabled = false; + this.enabled3 = false; + this.methodsNamingEnabled = true; + this.outputJarCommentEnabled = true; + this.outputJarComment = null; + this.stringEncryptionSeed = '\uffff'; + this.stringEncryptionVersion = 1; + this.globalStringEncryptionEnabled = false; + this.packageStringEncryptionEnabled = false; + this.decryptorIncludePattern = ""; + this.decryptorExcludePattern = ""; + this.java6Enabled = false; + this.text6 = "org.springframework.boot."; + } + + public boolean matchesMethod(ClassStorage classStorage, ClassGen classGen, Method method) { + return classStorage == null + ? false + : this.ruleSet4.calculateCount(classStorage, classGen, method) > 0; + } + + public void setEnabled8(boolean finalizeEnabled) { + this.finalizeEnabled = finalizeEnabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public int calculateCount(ClassStorage classStorage, ClassGen classGen) { + if (!this.packageStringEncryptionEnabled && classGen.getClassName().startsWith(this.text6)) { + return 0; + } + AnnotationEntryGen[] annotationEntryGens; + int value = (annotationEntryGens = classGen.getAnnotationEntries()).length; + int value2; + for (int value3 = value2 = 0; value3 < value; value3 = ++value2) { + AnnotationEntryGen annotationEntryGen = annotationEntryGens[value2]; + if ("Lcom/allatori/annotations/DisableStringEncryption;" + .equals(annotationEntryGen.getText2())) { + return 0; + } + if ("Lcom/allatori/annotations/EnableStringEncryption;" + .equals(annotationEntryGen.getText2())) { + return 1; + } + if ("Lcom/allatori/annotations/MaximumStringEncryption;" + .equals(annotationEntryGen.getText2())) { + return 3; + } + List values; + if ("Lcom/allatori/annotations/StringEncryption;".equals(annotationEntryGen.getText2()) + && (values = annotationEntryGen.getValues()) != null + && values.size() > 0 + && ((ElementValuePairGen) values.get(0)).getValue() != null) { + if ("enable".equals(((ElementValuePairGen) values.get(0)).getValue().stringifyValue())) { + return 1; + } + if ("disable".equals(((ElementValuePairGen) values.get(0)).getValue().stringifyValue())) { + return 0; + } + if ("maximum".equals(((ElementValuePairGen) values.get(0)).getValue().stringifyValue())) { + return 2; + } + if ("maximum-with-warnings" + .equals(((ElementValuePairGen) values.get(0)).getValue().stringifyValue())) { + return 3; + } + } + } + return this.ruleSet6.calculateCount(classStorage, classGen); + } + + public boolean isGlobalStringEncryptionEnabled() { + return this.globalStringEncryptionEnabled; + } + + public void setEnabled5(boolean packageStringEncryptionEnabled) { + this.packageStringEncryptionEnabled = packageStringEncryptionEnabled; + } + + public boolean isMethodsNamingEnabled() { + return this.methodsNamingEnabled; + } + + public void setRandomSeed(String randomSeed) { + this.randomSeed = randomSeed; + } + + public String getDecryptorIncludePattern() { + return this.decryptorIncludePattern; + } + + public String getDecryptorExcludePattern() { + return this.decryptorExcludePattern; + } + + public int calculateCount2(ClassStorage classStorage, ClassGen classGen) { + return this.ruleSet3.calculateCount(classStorage, classGen); + } + + public Hashtable getEntries() { + return this.entries; + } + + public String getStringEncryptionIgnoredStrings() { + return this.stringEncryptionIgnoredStrings; + } + + public void setStringEncryptionVersion(int stringEncryptionVersion) { + this.stringEncryptionVersion = stringEncryptionVersion; + } + + public void processRuleEntry(RuleEntry ruleEntry) { + this.ruleSet7.processRuleEntry(ruleEntry); + } + + public int calculateCount(ClassStorage classStorage, ClassGen classGen, MethodGen methodGen) { + if (this.enabled) { + return 0; + } + AnnotationEntryGen[] annotationEntryGens; + int value = (annotationEntryGens = classGen.getAnnotationEntries()).length; + int value2; + for (int value3 = value2 = 0; value3 < value; value3 = ++value2) { + AnnotationEntryGen annotationEntryGen = annotationEntryGens[value2]; + if ("Lcom/allatori/annotations/StrongStringEncryptionType;" + .equals(annotationEntryGen.getText2())) { + return 1; + } + if ("Lcom/allatori/annotations/FastStringEncryptionType;" + .equals(annotationEntryGen.getText2())) { + return 0; + } + List values; + if ("Lcom/allatori/annotations/StringEncryptionType;".equals(annotationEntryGen.getText2()) + && (values = annotationEntryGen.getValues()) != null + && values.size() > 0 + && ((ElementValuePairGen) values.get(0)).getValue() != null) { + if ("fast".equals(((ElementValuePairGen) values.get(0)).getValue().stringifyValue())) { + return 0; + } + if ("strong".equals(((ElementValuePairGen) values.get(0)).getValue().stringifyValue())) { + return 1; + } + } + } + return this.ruleSet5.calculateCount(classStorage, classGen, methodGen); + } + + public void setEnabled2(boolean outputJarCommentEnabled) { + this.outputJarCommentEnabled = outputJarCommentEnabled; + } + + public void processRuleEntry2(RuleEntry ruleEntry) { + this.ruleSet4.processRuleEntry(ruleEntry); + } + + public boolean isPackageStringEncryptionEnabled() { + return this.packageStringEncryptionEnabled; + } + + public void processRuleEntry3(RuleEntry ruleEntry) { + this.ruleSet.processRuleEntry(ruleEntry); + } + + public void setStringEncryptionIgnoredStrings(String stringEncryptionIgnoredStrings) { + this.stringEncryptionIgnoredStrings = stringEncryptionIgnoredStrings; + } + + public void processRuleEntry4(RuleEntry ruleEntry) { + this.ruleSet6.processRuleEntry(ruleEntry); + } + + public boolean matchesClassGen(ClassStorage classStorage, ClassGen classGen) { + return classStorage == null ? false : this.ruleSet7.calculateCount(classStorage, classGen) > 0; + } + + public void setEnabled6(boolean methodsNamingEnabled) { + this.methodsNamingEnabled = methodsNamingEnabled; + } + + public char getCharacter() { + return this.stringEncryptionSeed; + } + + public int getStringEncryptionVersion() { + return this.stringEncryptionVersion; + } + + public boolean isJava6Enabled() { + return this.java6Enabled; + } + + public void processRuleEntry5(RuleEntry ruleEntry) { + this.ruleSet5.processRuleEntry(ruleEntry); + } + + public void setDecryptorIncludePattern(String decryptorIncludePattern) { + this.decryptorIncludePattern = decryptorIncludePattern; + } + + public boolean isFinalizeEnabled() { + return this.finalizeEnabled; + } + + public String getOutputJarComment() { + return this.outputJarComment; + } + + public void processRuleEntry6(RuleEntry ruleEntry) { + this.ruleSet3.processRuleEntry(ruleEntry); + } + + public void setOutputJarComment(String outputJarComment) { + this.outputJarComment = outputJarComment; + } + + public boolean isEnabled3() { + return this.enabled3; + } + + public void setEnabled4(boolean java6Enabled) { + this.java6Enabled = java6Enabled; + } + + public boolean matchesMethodGen( + ClassStorage classStorage, ClassGen classGen, MethodGen methodGen) { + if (methodGen.getName().startsWith("Allatori")) { + return !Configuration.getObfuscationOptions().isEnabled(); + } + AnnotationEntryGen[] annotationEntryGens; + int value = (annotationEntryGens = methodGen.getAnnotationEntryGens()).length; + int value2; + for (int value3 = value2 = 0; value3 < value; value3 = ++value2) { + AnnotationEntryGen annotationEntryGen = annotationEntryGens[value2]; + if ("Lcom/allatori/annotations/DisableControlFlowObfuscation;" + .equals(annotationEntryGen.getText2())) { + return false; + } + if ("Lcom/allatori/annotations/EnableControlFlowObfuscation;" + .equals(annotationEntryGen.getText2())) { + return true; + } + List values; + if ("Lcom/allatori/annotations/ControlFlowObfuscation;".equals(annotationEntryGen.getText2()) + && (values = annotationEntryGen.getValues()) != null + && values.size() > 0 + && ((ElementValuePairGen) values.get(0)).getValue() != null) { + if ("enable".equals(((ElementValuePairGen) values.get(0)).getValue().stringifyValue())) { + return true; + } + if ("disable".equals(((ElementValuePairGen) values.get(0)).getValue().stringifyValue())) { + return false; + } + } + } + AnnotationEntryGen[] annotationEntryGens2; + int value4 = (annotationEntryGens2 = classGen.getAnnotationEntries()).length; + int value5; + for (int value6 = value5 = 0; value6 < value4; value6 = ++value5) { + AnnotationEntryGen annotationEntryGen2 = annotationEntryGens2[value5]; + if ("Lcom/allatori/annotations/DisableControlFlowObfuscation;" + .equals(annotationEntryGen2.getText2())) { + return false; + } + if ("Lcom/allatori/annotations/EnableControlFlowObfuscation;" + .equals(annotationEntryGen2.getText2())) { + return true; + } + List values2; + if ("Lcom/allatori/annotations/ControlFlowObfuscation;".equals(annotationEntryGen2.getText2()) + && (values2 = annotationEntryGen2.getValues()) != null + && values2.size() > 0 + && ((ElementValuePairGen) values2.get(0)).getValue() != null) { + if ("enable".equals(((ElementValuePairGen) values2.get(0)).getValue().stringifyValue())) { + return true; + } + if ("disable".equals(((ElementValuePairGen) values2.get(0)).getValue().stringifyValue())) { + return false; + } + } + } + return this.ruleSet.calculateCount(classStorage, classGen, methodGen) > 0; + } + + public boolean matchesClassGen2(ClassStorage classStorage, ClassGen classGen) { + return classStorage == null ? false : this.ruleSet2.calculateCount(classStorage, classGen) > 0; + } + + public boolean isEnabled() { + return this.enabled; + } + + public void processRuleEntry7(RuleEntry ruleEntry) { + this.ruleSet2.processRuleEntry(ruleEntry); + } +} diff --git a/src/main/java/com/allatori/config/OptimizationOptions.java b/src/main/java/com/allatori/config/OptimizationOptions.java new file mode 100644 index 0000000..8cdc898 --- /dev/null +++ b/src/main/java/com/allatori/config/OptimizationOptions.java @@ -0,0 +1,63 @@ +package com.allatori.config; + +import com.allatori.config.rule.RuleEntry; +import com.allatori.config.rule.RuleSet; +import com.allatori.lib.bcel.classfile.Method; +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.model.ClassStorage; +import java.util.Vector; + +public class OptimizationOptions { + + public RuleSet ruleSet; + + public Vector values; + + public RuleSet ruleSet2; + + public final Configuration configuration; + + public boolean matchesClassGen(ClassStorage classStorage, ClassGen classGen) { + if (classStorage == null) { + return false; + } else { + return this.ruleSet.getValues() == 0 + ? false + : this.ruleSet.calculateCount(classStorage, classGen) > 0; + } + } + + public void processRuleEntry(RuleEntry ruleEntry) { + this.ruleSet.processRuleEntry(ruleEntry); + } + + public void processRuleEntry2(RuleEntry ruleEntry) { + this.ruleSet2.processRuleEntry(ruleEntry); + } + + public boolean matchesText(String text) { + return this.values.contains(text); + } + + public OptimizationOptions(Configuration configuration2) { + super(); + this.configuration = configuration2; + this.ruleSet = new RuleSet(0); + this.ruleSet2 = new RuleSet(0); + this.values = new Vector(); + } + + public boolean matchesMethod(ClassStorage classStorage, ClassGen classGen, Method method) { + if (classStorage == null) { + return false; + } else { + return this.ruleSet2.getValues() == 0 + ? false + : this.ruleSet2.calculateCount(classStorage, classGen, method) > 0; + } + } + + public void processText(String text) { + this.values.add(text); + } +} diff --git a/src/main/java/com/allatori/config/OutputOptions.java b/src/main/java/com/allatori/config/OutputOptions.java new file mode 100644 index 0000000..cb9e524 --- /dev/null +++ b/src/main/java/com/allatori/config/OutputOptions.java @@ -0,0 +1,43 @@ +package com.allatori.config; + +public class OutputOptions { + + public int compressionLevel; + + public String logFile; + + public final Configuration configuration; + + public boolean keepDuplicateEntries; + + public void setEnabled(boolean keepDuplicateEntries) { + this.keepDuplicateEntries = keepDuplicateEntries; + } + + public OutputOptions(Configuration configuration2) { + super(); + this.configuration = configuration2; + this.compressionLevel = -1; + this.keepDuplicateEntries = false; + } + + public void setCompressionLevel(int compressionLevel) { + this.compressionLevel = compressionLevel; + } + + public boolean isKeepDuplicateEntries() { + return this.keepDuplicateEntries; + } + + public void setLogFile(String logFile) { + this.logFile = logFile; + } + + public String getLogFile() { + return this.logFile; + } + + public int getCompressionLevel() { + return this.compressionLevel; + } +} diff --git a/src/main/java/com/allatori/config/PackageNameRule.java b/src/main/java/com/allatori/config/PackageNameRule.java new file mode 100644 index 0000000..4129ca3 --- /dev/null +++ b/src/main/java/com/allatori/config/PackageNameRule.java @@ -0,0 +1,20 @@ +package com.allatori.config; + +import com.allatori.config.rule.RuleEntry; + +public class PackageNameRule { + + public RuleEntry ruleEntry; + + public final PackageRenamingOptions packageRenamingOptions; + + public String text; + + public PackageNameRule( + PackageRenamingOptions packageRenamingOptions2, RuleEntry ruleEntry2, String text) { + super(); + this.packageRenamingOptions = packageRenamingOptions2; + this.ruleEntry = ruleEntry2; + this.text = text; + } +} diff --git a/src/main/java/com/allatori/config/PackageRenamingOptions.java b/src/main/java/com/allatori/config/PackageRenamingOptions.java new file mode 100644 index 0000000..f49a17d --- /dev/null +++ b/src/main/java/com/allatori/config/PackageRenamingOptions.java @@ -0,0 +1,53 @@ +package com.allatori.config; + +import com.allatori.config.rule.RuleEntry; +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.model.ClassStorage; +import java.util.Iterator; +import java.util.Vector; + +public class PackageRenamingOptions { + + public Vector values; + + public boolean enabled; + + public final Configuration configuration; + + public boolean isEnabled() { + return this.enabled; + } + + public boolean matchesText(ClassStorage classStorage, ClassGen classGen, String text2) { + if (classStorage != null && classGen != null && text2 != null) { + if (this.values.size() == 0) { + return false; + } + Iterator iterator2 = this.values.iterator(); + while (iterator2.hasNext()) { + PackageNameRule packageNameRule; + if ((packageNameRule = (PackageNameRule) iterator2.next()) + .ruleEntry.classRule.matches(classStorage, classGen) + && text2.matches(packageNameRule.text)) { + return true; + } + } + return false; + } else { + return false; + } + } + + public void processText(RuleEntry ruleEntry, String text) { + this.enabled = true; + String text2 = text.replaceAll("\\.", "\\\\.").replaceAll("\\*", ".*"); + this.values.add(new PackageNameRule(this, ruleEntry, text2)); + } + + public PackageRenamingOptions(Configuration configuration2) { + super(); + this.configuration = configuration2; + this.enabled = false; + this.values = new Vector(); + } +} diff --git a/src/main/java/com/allatori/config/RenamingOptions.java b/src/main/java/com/allatori/config/RenamingOptions.java new file mode 100644 index 0000000..c33f835 --- /dev/null +++ b/src/main/java/com/allatori/config/RenamingOptions.java @@ -0,0 +1,186 @@ +package com.allatori.config; + +import com.allatori.config.rule.RuleEntry; +import com.allatori.config.rule.RuleSet; +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.model.ClassStorage; + +public class RenamingOptions { + + public String defaultPackage; + + public boolean enabled; + + public NameGenerationOptions nameGenerationOptions; + + public boolean compatibleRenamingEnabled; + + public KeepNamesOptions keepNamesOptions; + + public boolean randomizeNamesEnabled; + + public LocalVariableOptions localVariableOptions; + + public String incrementalObfuscation; + + public boolean classesNamingEnabled; + + public boolean skipRenamingEnabled; + + public RuleSet ruleSet; + + public boolean fieldsNamingEnabled; + + public final Configuration configuration; + + public LineNumberOptions lineNumberOptions; + + public ResourceRenamingOptions resourceRenamingOptions; + + public boolean forceDefaultPackageEnabled; + + public boolean enabled8; + + public boolean isSkipRenamingEnabled() { + return this.skipRenamingEnabled; + } + + public void setIncrementalObfuscation(String incrementalObfuscation) { + this.incrementalObfuscation = incrementalObfuscation; + } + + public void setEnabled2(boolean compatibleRenamingEnabled) { + this.compatibleRenamingEnabled = compatibleRenamingEnabled; + } + + public boolean isForceDefaultPackageEnabled() { + return this.forceDefaultPackageEnabled; + } + + public RenamingOptions(Configuration configuration2) { + super(); + this.configuration = configuration2; + this.skipRenamingEnabled = false; + this.forceDefaultPackageEnabled = false; + this.enabled8 = false; + this.fieldsNamingEnabled = false; + this.randomizeNamesEnabled = true; + this.enabled = false; + this.compatibleRenamingEnabled = false; + this.classesNamingEnabled = false; + this.ruleSet = new RuleSet(0); + this.keepNamesOptions = new KeepNamesOptions(this, null); + this.lineNumberOptions = new LineNumberOptions(this); + this.nameGenerationOptions = new NameGenerationOptions(this, null); + this.localVariableOptions = new LocalVariableOptions(this); + this.resourceRenamingOptions = new ResourceRenamingOptions(this); + } + + public KeepNamesOptions getKeepNamesOptions() { + return this.keepNamesOptions; + } + + public NameGenerationOptions getNameGenerationOptions() { + return this.nameGenerationOptions; + } + + public LocalVariableOptions getLocalVariableOptions() { + return this.localVariableOptions; + } + + public boolean matchesClassGen(ClassStorage classStorage, ClassGen classGen) { + return this.ruleSet.calculateCount(classStorage, classGen) == 1; + } + + public LineNumberOptions getLineNumberOptions() { + return this.lineNumberOptions; + } + + public void setEnabled3(boolean randomizeNamesEnabled) { + this.randomizeNamesEnabled = randomizeNamesEnabled; + } + + public boolean isClassesNamingEnabled() { + return this.classesNamingEnabled; + } + + public static boolean matchesRenamingOptions(RenamingOptions renamingOptions) { + return renamingOptions.skipRenamingEnabled; + } + + public ResourceRenamingOptions getResourceRenamingOptions() { + return this.resourceRenamingOptions; + } + + public boolean isEnabled() { + return this.enabled; + } + + public void setEnabled4(boolean classesNamingEnabled) { + this.classesNamingEnabled = classesNamingEnabled; + } + + public void processRuleEntry(RuleEntry ruleEntry) { + this.ruleSet.processRuleEntry(ruleEntry); + } + + public boolean isText2() { + return this.incrementalObfuscation != null; + } + + public void setEnabled8(boolean enabled8) { + this.enabled8 = enabled8; + } + + public void setEnabled7(boolean forceDefaultPackageEnabled) { + this.forceDefaultPackageEnabled = forceDefaultPackageEnabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public void setDefaultPackage(String defaultPackage) { + this.defaultPackage = defaultPackage; + } + + public boolean isFieldsNamingEnabled() { + return this.fieldsNamingEnabled; + } + + public static LocalVariableOptions getLocalVariableOptions(RenamingOptions renamingOptions) { + return renamingOptions.localVariableOptions; + } + + public void setEnabled6(boolean fieldsNamingEnabled) { + this.fieldsNamingEnabled = fieldsNamingEnabled; + } + + public boolean isEnabled8() { + return this.enabled8; + } + + public String getDefaultPackage() { + return this.defaultPackage; + } + + public boolean isCompatibleRenamingEnabled() { + return this.compatibleRenamingEnabled; + } + + public boolean isRandomizeNamesEnabled() { + return this.randomizeNamesEnabled; + } + + public String getIncrementalObfuscation() { + return this.incrementalObfuscation; + } + + public boolean isText() { + return this.defaultPackage != null; + } + + public void setEnabled5(boolean skipRenamingEnabled) { + this.skipRenamingEnabled = skipRenamingEnabled; + } +} diff --git a/src/main/java/com/allatori/config/ResourceNameRule.java b/src/main/java/com/allatori/config/ResourceNameRule.java new file mode 100644 index 0000000..28ff4cc --- /dev/null +++ b/src/main/java/com/allatori/config/ResourceNameRule.java @@ -0,0 +1,36 @@ +package com.allatori.config; + +public class ResourceNameRule { + + public final ResourceRenamingOptions resourceRenamingOptions; + + public boolean enabled; + + public String text; + + public String text2; + + public static boolean matchesResourceNameRule(ResourceNameRule resourceNameRule) { + return resourceNameRule.enabled; + } + + public static String getText(ResourceNameRule resourceNameRule) { + return resourceNameRule.text; + } + + public static String getText2(ResourceNameRule resourceNameRule) { + return resourceNameRule.text2; + } + + public ResourceNameRule( + ResourceRenamingOptions resourceRenamingOptions2, + String text, + boolean enabled, + String text2) { + super(); + this.resourceRenamingOptions = resourceRenamingOptions2; + this.text = text; + this.enabled = enabled; + this.text2 = text2; + } +} diff --git a/src/main/java/com/allatori/config/ResourceRenamingOptions.java b/src/main/java/com/allatori/config/ResourceRenamingOptions.java new file mode 100644 index 0000000..0490220 --- /dev/null +++ b/src/main/java/com/allatori/config/ResourceRenamingOptions.java @@ -0,0 +1,69 @@ +package com.allatori.config; + +import java.util.Locale; +import java.util.Vector; + +public class ResourceRenamingOptions { + + public boolean updateResourceNamesEnabled; + + public Vector values; + + public final RenamingOptions renamingOptions; + + public void processText(String text, boolean matches, String text2) { + String text3 = text.replaceAll("\\.", "\\\\.").replaceAll("\\*", ".*"); + this.values.add(new ResourceNameRule(this, text3, matches, text2)); + } + + public boolean matchesText(String text) { + String text2; + if (!(text2 = text.toLowerCase(Locale.ENGLISH)).endsWith(".jar") + && !text2.endsWith(".class") + && !text2.endsWith(".jks") + && !text2.endsWith(".ttf") + && !text2.endsWith(".png") + && !text2.endsWith(".jpg") + && !text2.endsWith(".jpeg") + && !text2.endsWith(".gif") + && !text2.endsWith(".bmp") + && !text2.endsWith(".svg") + && !text2.endsWith(".ico")) { + for (ResourceNameRule resourceNameRule : + ((Iterable) ((Iterable) this.values))) { + if (text.matches(ResourceNameRule.getText(resourceNameRule))) { + return ResourceNameRule.matchesResourceNameRule(resourceNameRule); + } + } + return false; + } else { + return false; + } + } + + public String getText(String text) { + text.toLowerCase(Locale.ENGLISH); + for (ResourceNameRule resourceNameRule : + ((Iterable) ((Iterable) this.values))) { + if (text.matches(ResourceNameRule.getText(resourceNameRule))) { + return ResourceNameRule.getText2(resourceNameRule); + } + } + return "UTF-8"; + } + + public void setEnabled(boolean updateResourceNamesEnabled) { + this.updateResourceNamesEnabled = updateResourceNamesEnabled; + } + + public ResourceRenamingOptions(RenamingOptions renamingOptions2) { + super(); + this.renamingOptions = renamingOptions2; + this.updateResourceNamesEnabled = false; + this.values = new Vector(); + } + + public boolean isUpdateResourceNamesEnabled() { + return this.updateResourceNamesEnabled; + } +} diff --git a/src/main/java/com/allatori/config/SyntheticOptions.java b/src/main/java/com/allatori/config/SyntheticOptions.java new file mode 100644 index 0000000..a68b687 --- /dev/null +++ b/src/main/java/com/allatori/config/SyntheticOptions.java @@ -0,0 +1,67 @@ +package com.allatori.config; + +import com.allatori.config.rule.RuleEntry; +import com.allatori.config.rule.RuleSet; +import com.allatori.lib.bcel.classfile.AnnotationEntry; +import com.allatori.lib.bcel.classfile.Field; +import com.allatori.lib.bcel.classfile.Method; +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.model.ClassStorage; + +public class SyntheticOptions { + + public RuleSet ruleSet; + + public RuleSet ruleSet2; + + public final Configuration configuration; + + public boolean matchesMethod(ClassStorage classStorage, ClassGen classGen, Method method) { + if (classStorage == null) { + return false; + } + AnnotationEntry[] annotationEntries = method.getAnnotationEntries(); + int value; + for (int value2 = value = 0; value2 < annotationEntries.length; value2 = ++value) { + AnnotationEntry annotationEntry = annotationEntries[value]; + if ("Lcom/allatori/annotations/Synthetize;".equals(annotationEntry.getText())) { + return true; + } + } + return this.ruleSet2.getValues() == 0 + ? method.isEnabled9() + : this.ruleSet2.calculateCount(classStorage, classGen, method) > 0; + } + + public void processRuleEntry(RuleEntry ruleEntry) { + this.ruleSet.processRuleEntry(ruleEntry); + } + + public SyntheticOptions(Configuration configuration2) { + super(); + this.configuration = configuration2; + this.ruleSet = new RuleSet(0); + this.ruleSet2 = new RuleSet(0); + } + + public void processRuleEntry2(RuleEntry ruleEntry) { + this.ruleSet2.processRuleEntry(ruleEntry); + } + + public boolean matchesField(ClassStorage classStorage, ClassGen classGen, Field field) { + if (classStorage == null) { + return false; + } + AnnotationEntry[] annotationEntries = field.getAnnotationEntries(); + int value; + for (int value2 = value = 0; value2 < annotationEntries.length; value2 = ++value) { + AnnotationEntry annotationEntry = annotationEntries[value]; + if ("Lcom/allatori/annotations/Synthetize;".equals(annotationEntry.getText())) { + return true; + } + } + return this.ruleSet.getValues() == 0 + ? false + : this.ruleSet.calculateCount(classStorage, classGen, field) > 0; + } +} diff --git a/src/main/java/com/allatori/config/WatermarkOptions.java b/src/main/java/com/allatori/config/WatermarkOptions.java new file mode 100644 index 0000000..4672511 --- /dev/null +++ b/src/main/java/com/allatori/config/WatermarkOptions.java @@ -0,0 +1,42 @@ +package com.allatori.config; + +public class WatermarkOptions { + + public boolean enabled; + + public String text; + + public final Configuration configuration; + + public String text2; + + public void setText(String text) { + this.text = text; + } + + public WatermarkOptions(Configuration configuration2) { + super(); + this.configuration = configuration2; + this.enabled = false; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public boolean isEnabled() { + return this.enabled; + } + + public void setText2(String text2) { + this.text2 = text2; + } + + public String getText2() { + return this.text2; + } + + public String getText() { + return this.text; + } +} diff --git a/src/main/java/com/allatori/config/XmlParsingContext.java b/src/main/java/com/allatori/config/XmlParsingContext.java new file mode 100644 index 0000000..35b2ea6 --- /dev/null +++ b/src/main/java/com/allatori/config/XmlParsingContext.java @@ -0,0 +1,34 @@ +package com.allatori.config; + +import java.io.FileReader; +import javax.xml.parsers.SAXParserFactory; +import org.xml.sax.InputSource; +import org.xml.sax.XMLReader; + +public class XmlParsingContext implements ConfigurationSource { + + public String text; + + @Override + public void parse() throws ConfigurationException { + try { + FileReader fileReader = new FileReader(this.text); + XMLReader xMLReader = SAXParserFactory.newInstance().newSAXParser().getXMLReader(); + xMLReader.setContentHandler(new ConfigurationHandler(this, null)); + xMLReader.parse(new InputSource(fileReader)); + } catch (ConfigurationSaxException configurationSaxException) { + throw new ConfigurationException(configurationSaxException.getMessage()); + } catch (Exception exception) { + throw new ConfigurationException(exception); + } + } + + public XmlParsingContext(String text) { + super(); + this.text = text; + } + + public static String getText(XmlParsingContext xmlParsingContext) { + return xmlParsingContext.text; + } +} diff --git a/src/main/java/com/allatori/config/property/PropertyHandler.java b/src/main/java/com/allatori/config/property/PropertyHandler.java new file mode 100644 index 0000000..6436c8a --- /dev/null +++ b/src/main/java/com/allatori/config/property/PropertyHandler.java @@ -0,0 +1,6 @@ +package com.allatori.config.property; + +public abstract class PropertyHandler { + + public abstract void apply(String text, String text2); +} diff --git a/src/main/java/com/allatori/config/property/PropertyRegistry.java b/src/main/java/com/allatori/config/property/PropertyRegistry.java new file mode 100644 index 0000000..31fa920 --- /dev/null +++ b/src/main/java/com/allatori/config/property/PropertyRegistry.java @@ -0,0 +1,30 @@ +package com.allatori.config.property; + +import com.allatori.config.ConfigurationException; + +public class PropertyRegistry { + + public static Object[][] values = + new Object[][] {{"string-encryption", StringEncryptionProperty.class}, {"", ""}, {"", ""}}; + + public static String text3 = "enable"; + + public static String text = "disable"; + + public static String text2 = "maximum"; + + public static PropertyHandler createPropertyHandler(String text) throws ConfigurationException { + int value; + for (int value2 = value = values.length - 1; value2 >= 0; value2 = --value) { + if (text.equals(values[value][0])) { + Class classValue = (Class) values[value][1]; + try { + return (PropertyHandler) classValue.newInstance(); + } catch (Exception exception) { + throw new ConfigurationException("Cannot instantiate property class"); + } + } + } + throw new ConfigurationException("Unknown property"); + } +} diff --git a/src/main/java/com/allatori/config/property/StringEncryptionProperty.java b/src/main/java/com/allatori/config/property/StringEncryptionProperty.java new file mode 100644 index 0000000..dcb53b9 --- /dev/null +++ b/src/main/java/com/allatori/config/property/StringEncryptionProperty.java @@ -0,0 +1,7 @@ +package com.allatori.config.property; + +public class StringEncryptionProperty extends PropertyHandler { + + @Override + public void apply(String text, String text2) {} +} diff --git a/src/main/java/com/allatori/config/rule/ClassRule.java b/src/main/java/com/allatori/config/rule/ClassRule.java new file mode 100644 index 0000000..1f414ca --- /dev/null +++ b/src/main/java/com/allatori/config/rule/ClassRule.java @@ -0,0 +1,197 @@ +package com.allatori.config.rule; + +import com.allatori.config.ConfigurationException; +import com.allatori.lib.bcel.classfile.Field; +import com.allatori.lib.bcel.classfile.Method; +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.lib.bcel.generic.MethodGen; +import com.allatori.model.ClassStorage; +import java.util.Vector; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class ClassRule { + + public Vector values; + + public String[] texts; + + public int count; + + public boolean enabled; + + public boolean enabled2; + + public String text; + + public boolean enabled3; + + public String text2; + + public String text3; + + public String text4; + + public Vector values2; + + public boolean enabled4 = false; + + public ClassRule( + String text, boolean matches, boolean matches2, boolean enabled4, boolean enabled3) + throws ConfigurationException { + this(text, matches, matches2); + this.enabled4 = enabled4; + this.enabled3 = enabled3; + } + + public boolean matches(MethodGen methodGen) { + int value; + for (int value2 = value = 0; value2 < this.values.size(); value2 = ++value) { + MethodRule methodRule; + if ((methodRule = (MethodRule) this.values.get(value)).matches(methodGen)) { + if (!methodRule.matches()) { + return true; + } + return false; + } + } + return false; + } + + public boolean matches() { + return this.enabled2; + } + + public ClassRule(String text, boolean enabled, boolean enabled2) throws ConfigurationException { + super(); + this.enabled4 = false; + this.enabled3 = false; + this.values2 = new Vector(); + this.values = new Vector(); + this.enabled = enabled; + this.enabled2 = enabled2; + this.processText(text); + } + + public void processText(String text5) throws ConfigurationException { + Matcher matcher2; + if ((matcher2 = + Pattern.compile( + "(.*?(?:class|interface))\\s+(.+?)(?:\\s+extends\\s+(.+?))?(?:\\s+implements\\s+(.+?))?(?:\\s+instanceof\\s+(.+?))?") + .matcher(text5)) + .matches()) { + String text6 = matcher2.group(1); + this.count = TemplateUtils.calculateCount(text6); + Matcher matcher3; + if (TemplateUtils.matches2(text6)) { + int value; + if ((value = text6.indexOf(32)) == -1) { + value = text6.length(); + } + this.text = TemplateUtils.getText2(text6.substring(1, value)); + this.text = 'L' + this.text.replaceAll("\\\\\\.", "/") + ';'; + matcher3 = matcher2; + } else { + this.text = null; + matcher3 = matcher2; + } + String text7 = matcher3.group(2); + this.text2 = TemplateUtils.getText2(text7); + this.text3 = TemplateUtils.getText2(matcher2.group(3)); + this.texts = TemplateUtils.getTexts(matcher2.group(4)); + this.text4 = TemplateUtils.getText2(matcher2.group(5)); + } else { + throw new ConfigurationException("Invalid template."); + } + } + + public ClassRule() { + this.enabled3 = false; + this.values2 = new Vector(); + this.values = new Vector(); + } + + public boolean matches(ClassStorage classStorage, ClassGen classGen) { + if (!TemplateUtils.matches(classGen, this.count)) { + return this.enabled3; + } else if (!classGen.getClassName().matches(this.text2)) { + return this.enabled3; + } else if (!classGen.getSuperclassName().matches(this.text3)) { + return this.enabled3; + } else if (!TemplateUtils.matches(classGen.getInterfaceNames(), this.texts)) { + return this.enabled3; + } else if (!TemplateUtils.matches(classStorage, classGen.getClassName(), this.text4)) { + return this.enabled3; + } else { + return this.text != null && !TemplateUtils.matches(classGen.getAnnotationEntries(), this.text) + ? this.enabled3 + : !this.enabled3; + } + } + + public void processMethodRule(MethodRule methodRule) { + this.values.add(methodRule); + } + + public boolean matches2() { + return this.enabled; + } + + public void processFieldRule(FieldRule fieldRule) { + this.values2.add(fieldRule); + } + + public boolean matches(ClassStorage classStorage, Field field) { + int value; + for (int value2 = value = 0; value2 < this.values2.size(); value2 = ++value) { + FieldRule fieldRule; + if ((fieldRule = (FieldRule) this.values2.get(value)).matches(classStorage, field)) { + if (!fieldRule.matches()) { + return true; + } + return false; + } + } + return false; + } + + public boolean matches(Method method) { + int value; + for (int value2 = value = 0; value2 < this.values.size(); value2 = ++value) { + MethodRule methodRule; + if ((methodRule = (MethodRule) this.values.get(value)).matches(method)) { + if (!methodRule.matches()) { + return true; + } + return false; + } + } + return false; + } + + public boolean matches3() { + return this.enabled4; + } + + public ClassRule createClassRule() { + ClassRule classRule = new ClassRule(); + classRule.enabled = this.enabled; + classRule.enabled2 = this.enabled2; + classRule.enabled4 = this.enabled4; + classRule.count = this.count; + classRule.text2 = this.text2; + classRule.text3 = this.text3; + classRule.text4 = this.text4; + classRule.texts = this.texts; + classRule.text = this.text; + return classRule; + } + + public boolean matches4() { + return this.values2.size() > 0; + } + + public boolean matches5() { + return this.values.size() > 0; + } +} diff --git a/src/main/java/com/allatori/config/rule/FieldRule.java b/src/main/java/com/allatori/config/rule/FieldRule.java new file mode 100644 index 0000000..9456fc9 --- /dev/null +++ b/src/main/java/com/allatori/config/rule/FieldRule.java @@ -0,0 +1,96 @@ +package com.allatori.config.rule; + +import com.allatori.config.ConfigurationException; +import com.allatori.lib.bcel.classfile.Field; +import com.allatori.model.ClassStorage; + +public class FieldRule { + + public String text; + + public boolean enabled; + + public String text2; + + public String text3; + + public String text4; + + public boolean enabled2; + + public int count; + + public boolean matches(ClassStorage classStorage, Field field) { + if (!TemplateUtils.matches(field, this.count)) { + return this.enabled; + } + if (!field.getText().matches(this.text4)) { + return this.enabled; + } + if (!field.getType().toString().matches(this.text3)) { + return this.enabled; + } + if (this.text != null && !TemplateUtils.matches(field.getAnnotationEntries(), this.text)) { + return this.enabled; + } + if (this.text2 != null) { + String text5; + if ((text5 = field.getText2()).charAt(0) != 'L' || text5.charAt(text5.length() - 1) != ';') { + return this.enabled; + } + String text6 = text5.substring(1, text5.length() - 1).replace('/', '.'); + if (!TemplateUtils.matches(classStorage, text6, this.text2)) { + return this.enabled; + } + } + return !this.enabled; + } + + public void processText(String text5) throws ConfigurationException { + String[] texts; + if ((texts = text5.split("\\s+")) != null && texts.length != 0) { + int value; + FieldRule fieldRule; + if ((value = texts.length) >= 3 && "instanceof".equals(texts[value - 2])) { + int value2 = value - 1; + String[] texts2 = texts; + value -= 2; + fieldRule = this; + this.text2 = TemplateUtils.getText2(texts2[value2]); + } else { + fieldRule = this; + this.text2 = null; + } + fieldRule.text4 = TemplateUtils.getText(texts[value - 1]); + if (value > 1 + && !TemplateUtils.matches3(texts[value - 2]) + && !TemplateUtils.matches2(texts[value - 2])) { + fieldRule = this; + this.text3 = TemplateUtils.getText2(texts[value - 2]); + } else { + fieldRule = this; + this.text3 = ".*"; + } + fieldRule.count = TemplateUtils.calculateCount(text5); + if (TemplateUtils.matches2(texts[0])) { + this.text = TemplateUtils.getText2(texts[0].substring(1)); + this.text = 'L' + this.text.replaceAll("\\\\\\.", "/") + ';'; + } else { + this.text = null; + } + } else { + throw new ConfigurationException("Invalid template."); + } + } + + public FieldRule(String text, boolean enabled2, boolean enabled) throws ConfigurationException { + super(); + this.processText(text); + this.enabled2 = enabled2; + this.enabled = enabled; + } + + public boolean matches() { + return this.enabled2; + } +} diff --git a/src/main/java/com/allatori/config/rule/MethodRule.java b/src/main/java/com/allatori/config/rule/MethodRule.java new file mode 100644 index 0000000..f530ad4 --- /dev/null +++ b/src/main/java/com/allatori/config/rule/MethodRule.java @@ -0,0 +1,117 @@ +package com.allatori.config.rule; + +import com.allatori.config.ConfigurationException; +import com.allatori.lib.bcel.classfile.Method; +import com.allatori.lib.bcel.generic.MethodGen; + +public class MethodRule { + + public String text; + + public String text2; + + public String text3; + + public String text4; + + public boolean enabled; + + public boolean enabled2; + + public int count; + + public boolean matches(MethodGen methodGen) { + if (!TemplateUtils.matches(methodGen, this.count)) { + return this.enabled2; + } else if (!methodGen.getName().matches(this.text3)) { + return this.enabled2; + } else if (!methodGen.getReturnType().toString().matches(this.text)) { + return this.enabled2; + } else if (!TemplateUtils.matches(methodGen.getArgumentTypes(), this.text2)) { + return this.enabled2; + } else { + return this.text4 != null + && !TemplateUtils.matches(methodGen.getAnnotationEntryGens(), this.text4) + ? this.enabled2 + : !this.enabled2; + } + } + + public void processText(String text5) throws ConfigurationException { + String[] texts; + String[] texts2; + if ((texts = text5.split("\\(|\\)")).length != 2) { + if (texts.length == 1 && text5.endsWith("()")) { + texts2 = texts; + } else { + if (texts.length <= 2 || !text5.contains("regex:")) { + throw new ConfigurationException("Invalid template."); + } + String text6 = text5.substring(0, text5.lastIndexOf(40)); + String text7 = text5.substring(text5.lastIndexOf(40) + 1, text5.lastIndexOf(41)); + texts2 = texts = new String[] {text6, text7}; + } + } else { + texts2 = texts; + } + if (texts2.length == 1) { + texts2 = texts; + this.text2 = ""; + } else { + texts2 = texts; + String text8 = texts[1]; + this.text2 = TemplateUtils.getText4(text8); + } + String[] texts3; + String text9; + if ((texts3 = (text9 = texts2[0]).split("\\s+")) != null && texts3.length != 0) { + this.text3 = TemplateUtils.getText(texts3[texts3.length - 1]); + MethodRule methodRule; + if (texts3.length > 1 + && !TemplateUtils.matches3(texts3[texts3.length - 2]) + && !TemplateUtils.matches2(texts3[texts3.length - 2])) { + this.text = TemplateUtils.getText2(texts3[texts3.length - 2]); + methodRule = this; + } else { + methodRule = this; + this.text = ".*"; + } + methodRule.count = TemplateUtils.calculateCount(text9); + if (TemplateUtils.matches2(texts3[0])) { + this.text4 = TemplateUtils.getText2(texts3[0].substring(1)); + this.text4 = 'L' + this.text4.replaceAll("\\\\\\.", "/") + ';'; + } else { + this.text4 = null; + } + } else { + throw new ConfigurationException("Invalid template."); + } + } + + public boolean matches() { + return this.enabled; + } + + public MethodRule(String text, boolean enabled, boolean enabled2) throws ConfigurationException { + super(); + this.processText(text); + this.enabled = enabled; + this.enabled2 = enabled2; + } + + public boolean matches(Method method) { + if (!TemplateUtils.matches(method, this.count)) { + return this.enabled2; + } else if (!method.getText().matches(this.text3)) { + return this.enabled2; + } else if (!method.getReturnType().toString().matches(this.text)) { + return this.enabled2; + } else if (!TemplateUtils.matches(method.getArgumentTypes(), this.text2)) { + return this.enabled2; + } else { + return this.text4 != null && !TemplateUtils.matches(method.getAnnotationEntries(), this.text4) + ? this.enabled2 + : !this.enabled2; + } + } +} diff --git a/src/main/java/com/allatori/config/rule/RuleEntry.java b/src/main/java/com/allatori/config/rule/RuleEntry.java new file mode 100644 index 0000000..97ad633 --- /dev/null +++ b/src/main/java/com/allatori/config/rule/RuleEntry.java @@ -0,0 +1,14 @@ +package com.allatori.config.rule; + +public class RuleEntry { + + public int count; + + public ClassRule classRule; + + public RuleEntry(int count, ClassRule classRule2) { + super(); + this.count = count; + this.classRule = classRule2; + } +} diff --git a/src/main/java/com/allatori/config/rule/RuleSet.java b/src/main/java/com/allatori/config/rule/RuleSet.java new file mode 100644 index 0000000..1391367 --- /dev/null +++ b/src/main/java/com/allatori/config/rule/RuleSet.java @@ -0,0 +1,84 @@ +package com.allatori.config.rule; + +import com.allatori.lib.bcel.classfile.Field; +import com.allatori.lib.bcel.classfile.Method; +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.lib.bcel.generic.MethodGen; +import com.allatori.model.ClassStorage; +import java.util.Vector; + +public class RuleSet { + + public Vector values; + + public int count; + + public int getValues() { + return this.values.size(); + } + + public int calculateCount(ClassStorage classStorage, ClassGen classGen, Field field) { + int value; + for (int value2 = value = 0; value2 < this.values.size(); value2 = ++value) { + RuleEntry ruleEntry; + if ((ruleEntry = (RuleEntry) this.values.get(value)) + .classRule.matches(classStorage, classGen)) { + if (field == null) { + return ruleEntry.count; + } + if (ruleEntry.classRule.matches(classStorage, field)) { + return ruleEntry.count; + } + } + } + return this.count; + } + + public int calculateCount(ClassStorage classStorage, ClassGen classGen, Method method) { + int value; + for (int value2 = value = 0; value2 < this.values.size(); value2 = ++value) { + RuleEntry ruleEntry; + if ((ruleEntry = (RuleEntry) this.values.get(value)) + .classRule.matches(classStorage, classGen)) { + if (method == null) { + return ruleEntry.count; + } + if (ruleEntry.classRule.matches(method)) { + return ruleEntry.count; + } + } + } + return this.count; + } + + public RuleSet(int count) { + super(); + this.values = new Vector(); + this.count = count; + } + + public void processRuleEntry(RuleEntry ruleEntry) { + this.values.add(ruleEntry); + } + + public int calculateCount(ClassStorage classStorage, ClassGen classGen, MethodGen methodGen) { + int value; + for (int value2 = value = 0; value2 < this.values.size(); value2 = ++value) { + RuleEntry ruleEntry; + if ((ruleEntry = (RuleEntry) this.values.get(value)) + .classRule.matches(classStorage, classGen)) { + if (methodGen == null) { + return ruleEntry.count; + } + if (ruleEntry.classRule.matches(methodGen)) { + return ruleEntry.count; + } + } + } + return this.count; + } + + public int calculateCount(ClassStorage classStorage, ClassGen classGen) { + return this.calculateCount(classStorage, classGen, (MethodGen) null); + } +} diff --git a/src/main/java/com/allatori/config/rule/TemplateUtils.java b/src/main/java/com/allatori/config/rule/TemplateUtils.java new file mode 100644 index 0000000..3f50a33 --- /dev/null +++ b/src/main/java/com/allatori/config/rule/TemplateUtils.java @@ -0,0 +1,352 @@ +package com.allatori.config.rule; + +import com.allatori.lib.bcel.classfile.AccessFlags; +import com.allatori.lib.bcel.classfile.AnnotationEntry; +import com.allatori.lib.bcel.generic.AnnotationEntryGen; +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.lib.bcel.generic.Type; +import com.allatori.model.ClassStorage; +import com.allatori.util.Log; + +public class TemplateUtils { + + public static final int COUNT = 2048; + + public static final int COUNT2 = 512; + + public static final int COUNT3 = 32; + + public static final int COUNT4 = 8192; + + public static final int COUNT5 = 128; + + public static final int COUNT6 = 4; + + public static final int COUNT7 = 256; + + public static final int COUNT8 = 1; + + public static final int COUNT9 = 2; + + public static final int COUNT10 = 8; + + public static final int COUNT11 = 1024; + + public static final int COUNT12 = 16; + + public static final int COUNT13 = 4096; + + public static final int COUNT14 = 64; + + public static boolean matches(String text) { + if (text.equals("public")) { + return true; + } else if (text.equals("protected")) { + return true; + } else if (text.equals("package")) { + return true; + } else if (text.equals("private")) { + return true; + } else if (text.equals("protected+")) { + return true; + } else { + return text.equals("package+") ? true : text.equals("private+"); + } + } + + public static boolean matches(String[] texts, String[] texts2) { + int value; + int value2; + for (int value3 = value2 = texts2.length - 1; value3 >= 0; value3 = --value2) { + byte value4 = 0; + int value5; + value3 = value5 = texts.length - 1; + while (true) { + if (value3 < 0) { + value = value4; + break; + } + if (texts[value5].matches(texts2[value2])) { + value = 1; + break; + } + value3 = --value5; + } + if (value == 0) { + return false; + } + } + return true; + } + + public static String getText(String text) { + return getText2(text); + } + + public static String getText2(String text) { + return text == null ? ".*" : getText3(text.trim().replaceAll("\\$", "\\\\\\$")); + } + + public static String getText3(String text) { + return text.startsWith("regex:") + ? text.substring(6) + : text.replaceAll("\\.", "\\\\.").replaceAll("\\*", ".*"); + } + + public static boolean matches(AnnotationEntry[] annotationEntrys, String text) { + if (text == null) { + return true; + } + int value; + for (int value2 = value = annotationEntrys.length - 1; value2 >= 0; value2 = --value) { + if (annotationEntrys[value].getText().matches(text)) { + return true; + } + } + return false; + } + + public static String[] getTexts(String text) { + if (text == null) { + return new String[0]; + } + String[] texts; + if ((texts = text.split("\\s*,\\s*")) == null) { + return new String[0]; + } + int value; + for (int value2 = value = texts.length - 1; value2 >= 0; value2 = value) { + texts[value] = texts[value].replaceAll("\\$", "\\\\\\$"); + String text3 = getText3(texts[value]); + int value3 = value; + String[] texts2 = texts; + value--; + texts2[value3] = text3; + } + return texts; + } + + public static int calculateCount(String text) { + String text2 = text.trim(); + short value = 0; + if (text2.indexOf("public") >= 0) { + value = 1; + } + if (text2.indexOf("protected") >= 0) { + value |= 2; + } + if (text2.indexOf("package") >= 0) { + value |= 4; + } + if (text2.indexOf("private") >= 0) { + value |= 8; + } + if (text2.indexOf("protected+") >= 0) { + value |= 3; + } + if (text2.indexOf("package+") >= 0) { + value |= 7; + } + if (text2.indexOf("private+") >= 0) { + value |= 15; + } + if (value == 0) { + value = 15; + } + if (text2.indexOf("static") >= 0) { + value |= 16; + } + if (text2.indexOf("final") >= 0) { + value |= 32; + } + if (text2.indexOf("synchronized") >= 0) { + value |= 64; + } + if (text2.indexOf("volatile") >= 0) { + value |= 128; + } + if (text2.indexOf("transient") >= 0) { + value |= 256; + } + if (text2.indexOf("native") >= 0) { + value |= 512; + } + if (text2.indexOf("interface") >= 0) { + value |= 1024; + } + if (text2.indexOf("abstract") >= 0) { + value |= 2048; + } + if (text2.indexOf("strictfp") >= 0) { + value |= 4096; + } + if (text2.indexOf("enum") >= 0) { + value |= 8192; + } + return value; + } + + public static boolean matches2(String text) { + return text.charAt(0) == '@'; + } + + public static boolean matches3(String text) { + if (text.indexOf("public") >= 0) { + return true; + } else if (text.indexOf("protected") >= 0) { + return true; + } else if (text.indexOf("package") >= 0) { + return true; + } else if (text.indexOf("private") >= 0) { + return true; + } else if (text.indexOf("static") >= 0) { + return true; + } else if (text.indexOf("final") >= 0) { + return true; + } else if (text.indexOf("synchronized") >= 0) { + return true; + } else if (text.indexOf("volatile") >= 0) { + return true; + } else if (text.indexOf("transient") >= 0) { + return true; + } else if (text.indexOf("native") >= 0) { + return true; + } else if (text.indexOf("interface") >= 0) { + return true; + } else if (text.indexOf("abstract") >= 0) { + return true; + } else { + return text.indexOf("strictfp") >= 0 ? true : text.indexOf("enum") >= 0; + } + } + + public static boolean matches(AnnotationEntryGen[] annotationEntryGens, String text) { + if (text == null) { + return true; + } + int value; + for (int value2 = value = annotationEntryGens.length - 1; value2 >= 0; value2 = --value) { + try { + if (annotationEntryGens[value].getText2().matches(text)) { + return true; + } + } catch (ClassCastException classCastException) { + throw classCastException; + } + } + return false; + } + + public static boolean matches(ClassStorage classStorage, String text, String text2) { + if (text == null) { + return false; + } + if (text.matches(text2)) { + return true; + } + ClassGen classGen; + if ((classGen = classStorage.getClassGen(text)) != null) { + int value; + String[] texts; + for (int value2 = value = (texts = classGen.getInterfaceNames()).length - 1; + value2 >= 0; + value2 = --value) { + if (matches(classStorage, texts[value], text2)) { + return true; + } + } + return matches(classStorage, classGen.getSuperclassName(), text2); + } else { + try { + int value3; + Class classValue; + Class[] classs; + for (int value4 = + value3 = + (classs = + (classValue = + Class.forName(text, false, classStorage.getClassLoader())) + .getInterfaces()) + .length + - 1; + value4 >= 0; + value4 = --value3) { + if (matches(classStorage, classs[value3].getName(), text2)) { + return true; + } + } + return classValue.getSuperclass() != null + ? matches(classStorage, classValue.getSuperclass().getName(), text2) + : false; + } catch (ClassNotFoundException classNotFoundException) { + return true; + } catch (SecurityException securityException) { + Log.error("Cannot read class: " + text); + throw securityException; + } + } + } + + public static boolean matches(Type[] types, String text) { + StringBuffer stringBuffer = new StringBuffer(""); + int value; + for (int value2 = value = types.length - 1; value2 >= 0; value2 = value) { + StringBuilder stringBuilder = new StringBuilder().append(types[value].toString()); + value--; + stringBuffer.insert((byte) 0, stringBuilder.append((String) ",").toString()); + } + if (stringBuffer.length() > 0) { + stringBuffer.deleteCharAt(stringBuffer.length() - 1); + } + return stringBuffer.toString().matches(text); + } + + public static String getText4(String text) { + return text.replaceAll("\\s+", "") + .replaceAll("\\[", "\\\\[") + .replaceAll("]", "\\\\]") + .replaceAll("\\.", "\\\\.") + .replaceAll("\\*\\*", "%@#") + .replaceAll("\\*", "[^,]*") + .replaceAll("\\%\\@\\#", ".*"); + } + + public static boolean matches(AccessFlags accessFlags, int value) { + if (accessFlags.isEnabled6()) { + if ((value & 1) == 0) { + return false; + } + } else if (accessFlags.isEnabled13()) { + if ((value & 2) == 0) { + return false; + } + } else if (accessFlags.isEnabled9()) { + if ((value & 8) == 0) { + return false; + } + } else if ((value & 4) == 0) { + return false; + } + if ((value & 16) > 0 && !accessFlags.isEnabled11()) { + return false; + } else if ((value & 32) > 0 && !accessFlags.isEnabled3()) { + return false; + } else if ((value & 64) > 0 && !accessFlags.isEnabled12()) { + return false; + } else if ((value & 128) > 0 && !accessFlags.isEnabled()) { + return false; + } else if ((value & 256) > 0 && !accessFlags.isEnabled4()) { + return false; + } else if ((value & 512) > 0 && !accessFlags.isEnabled14()) { + return false; + } else if ((value & 1024) > 0 && !accessFlags.isEnabled5()) { + return false; + } else if ((value & 2048) > 0 && !accessFlags.isEnabled15()) { + return false; + } else { + return (value & 4096) > 0 && !accessFlags.isEnabled7() + ? false + : (value & 8192) <= 0 || accessFlags.isEnabled10(); + } + } +} diff --git a/src/main/java/com/allatori/crypto/CustomStringEncryption.java b/src/main/java/com/allatori/crypto/CustomStringEncryption.java new file mode 100644 index 0000000..643ad09 --- /dev/null +++ b/src/main/java/com/allatori/crypto/CustomStringEncryption.java @@ -0,0 +1,120 @@ +package com.allatori.crypto; + +import com.allatori.config.Configuration; +import com.allatori.lib.bcel.generic.InstructionFactory; +import com.allatori.lib.bcel.generic.InvokeInstruction; +import com.allatori.lib.bcel.generic.Type; +import com.allatori.util.Log; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +public class CustomStringEncryption { + + public static String text = "allatori-custom-12321-32123:"; + + public static String createText( + String text, ClassLoader classLoader, String text2, String text3) { + String text4 = text; + String[] texts = null; + try { + int value = Integer.parseInt(text4.substring(text4.indexOf(91) + 1, text4.indexOf(93))); + text4 = text4.substring(text4.indexOf(93) + 1); + String text5; + if ((text5 = + (String) + Class.forName( + (texts = + (String[]) + Configuration.getObfuscationOptions().getEntries().get(value)) + [0], + true, + classLoader) + .getDeclaredMethod(texts[1], String.class, String.class, String.class) + .invoke(null, text4, text2, text3)) + == null) { + Log.error( + "Custom string encryption error: null value is returned by " + + texts[0] + + "." + + texts[1] + + "()"); + throw new NullPointerException(); + } else { + return text5; + } + } catch (ClassNotFoundException classNotFoundException) { + Log.error("Cannot load custom string encryption class (class not found): " + texts[0]); + return text4; + } catch (NoSuchMethodException noSuchMethodException) { + Log.error("Cannot find custom string encryption method: " + texts[0] + "." + texts[1] + "()"); + return text4; + } catch (Exception exception) { + Log.error("Custom string encryption error: " + exception.getMessage()); + return text4; + } + } + + public static InvokeInstruction getInvokeInstruction( + InstructionFactory instructionFactory, int value) { + String[] texts = (String[]) Configuration.getObfuscationOptions().getEntries().get(value); + return instructionFactory.createInvoke( + texts[2], texts[3], Type.STRING, new Type[] {Type.STRING}, (short) 184); + } + + public static String createText(String text2, int value, ClassLoader classLoader) { + String[] texts = (String[]) Configuration.getObfuscationOptions().getEntries().get(value); + try { + Class classValue = Class.forName(texts[0], true, classLoader); + try { + Method method; + if (!Modifier.isStatic( + (method = classValue.getDeclaredMethod(texts[1], String.class)).getModifiers()) + || !Modifier.isPublic(method.getModifiers())) { + Log.error( + "Custom string encryption method is not static and public: " + + texts[0] + + "." + + texts[1] + + "()"); + } + String text3; + if ((text3 = (String) method.invoke(null, text2)) == null) { + Log.error( + "Custom string encryption error: null value is returned by " + + texts[0] + + "." + + texts[1] + + "()"); + throw new NullPointerException(); + } else { + return text3; + } + } catch (NoSuchMethodException noSuchMethodException) { + Method method2; + if (!Modifier.isStatic( + (method2 = + classValue.getDeclaredMethod( + texts[1], String.class, String.class, String.class)) + .getModifiers()) + || !Modifier.isPublic(method2.getModifiers())) { + Log.error( + "Custom string encryption method is not static and public: " + + texts[0] + + "." + + texts[1] + + "()"); + } + return "" + text + '[' + value + ']' + text2; + } + } catch (ClassNotFoundException classNotFoundException) { + Log.error("Cannot load custom string encryption class (class not found): " + texts[0]); + return text2; + } catch (NoSuchMethodException noSuchMethodException2) { + Log.error("Cannot find custom string encryption method: " + texts[0] + "." + texts[1] + "()"); + return text2; + } catch (Exception exception) { + Log.error("Custom string encryption error: " + exception.getMessage()); + return text2; + } + } +} diff --git a/src/main/java/com/allatori/crypto/StringEncryptionUtils.java b/src/main/java/com/allatori/crypto/StringEncryptionUtils.java new file mode 100644 index 0000000..df210dd --- /dev/null +++ b/src/main/java/com/allatori/crypto/StringEncryptionUtils.java @@ -0,0 +1,738 @@ +package com.allatori.crypto; + +import com.allatori.bytecode.MethodFactory; +import com.allatori.config.Configuration; +import com.allatori.lib.bcel.classfile.Attribute; +import com.allatori.lib.bcel.classfile.Constant; +import com.allatori.lib.bcel.classfile.ConstantPool; +import com.allatori.lib.bcel.classfile.ConstantString; +import com.allatori.lib.bcel.classfile.ConstantUtf8; +import com.allatori.lib.bcel.classfile.ConstantValue; +import com.allatori.lib.bcel.classfile.Field; +import com.allatori.lib.bcel.classfile.Method; +import com.allatori.lib.bcel.classfile.SourceFile; +import com.allatori.lib.bcel.classfile.StackMap; +import com.allatori.lib.bcel.classfile.StackMapEntry; +import com.allatori.lib.bcel.classfile.StackMapType; +import com.allatori.lib.bcel.generic.ArrayType; +import com.allatori.lib.bcel.generic.BranchInstruction; +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.lib.bcel.generic.ConstantPoolGen; +import com.allatori.lib.bcel.generic.FieldGen; +import com.allatori.lib.bcel.generic.FieldInstruction; +import com.allatori.lib.bcel.generic.GETFIELD; +import com.allatori.lib.bcel.generic.GETSTATIC; +import com.allatori.lib.bcel.generic.IF_ACMPEQ; +import com.allatori.lib.bcel.generic.IF_ACMPNE; +import com.allatori.lib.bcel.generic.IINC; +import com.allatori.lib.bcel.generic.Instruction; +import com.allatori.lib.bcel.generic.InstructionConstants; +import com.allatori.lib.bcel.generic.InstructionFactory; +import com.allatori.lib.bcel.generic.InstructionHandle; +import com.allatori.lib.bcel.generic.InstructionList; +import com.allatori.lib.bcel.generic.InstructionTargeter; +import com.allatori.lib.bcel.generic.LDC; +import com.allatori.lib.bcel.generic.LineNumberGen; +import com.allatori.lib.bcel.generic.MethodGen; +import com.allatori.lib.bcel.generic.PUSH; +import com.allatori.lib.bcel.generic.PUTFIELD; +import com.allatori.lib.bcel.generic.PUTSTATIC; +import com.allatori.lib.bcel.generic.Type; +import com.allatori.util.Log; +import java.io.BufferedReader; +import java.io.FileReader; +import java.util.Collection; +import java.util.Vector; +import java.util.regex.Pattern; + +public class StringEncryptionUtils { + + public static Vector values = new Vector(); + + public static boolean matchesText(Vector vector, String text) { + if ("000".equals(text)) { + return false; + } + if ("001".equals(text)) { + vector.add(InstructionConstants.ICONST_1); + } else if ("010".equals(text)) { + vector.add(InstructionConstants.ICONST_2); + } else if ("011".equals(text)) { + vector.add(InstructionConstants.ICONST_3); + } else if ("100".equals(text)) { + vector.add(InstructionConstants.ICONST_4); + } else if ("101".equals(text)) { + vector.add(InstructionConstants.ICONST_5); + } else if ("110".equals(text)) { + vector.add(InstructionConstants.ICONST_3); + vector.add(InstructionConstants.ICONST_5); + vector.add(InstructionConstants.IXOR); + } else if ("111".equals(text)) { + vector.add(InstructionConstants.ICONST_2); + vector.add(InstructionConstants.ICONST_5); + vector.add(InstructionConstants.IXOR); + } + return true; + } + + public static void processCollection(ClassGen classGen, Collection values) { + InstructionHandle instructionHandle; + int value; + Field[] fields; + for (int value2 = value = (fields = classGen.getFields()).length - 1; + value2 >= 0; + value2 = --value) { + Constant constant; + ConstantValue constantValue; + if ((constantValue = fields[value].getConstantValue()) != null + && (constant = + classGen.getConstantPool().getConstant(constantValue.getConstantValueIndex())) + instanceof ConstantString) { + String bytes = + ((ConstantUtf8) + classGen + .getConstantPool() + .getConstant(((ConstantString) constant).getStringIndex())) + .getBytes(); + values.add(bytes); + } + } + Method[] methods; + int value3; + for (int value4 = value3 = (methods = classGen.getMethods()).length - 1; + value4 >= 0; + value4 = --value3) { + Method method; + if ((method = methods[value3]).getCode() != null) { + InstructionList instructionList; + InstructionHandle instructionHandle2; + InstructionHandle instructionHandle3 = + instructionHandle2 = + (instructionList = + MethodFactory.createMethodGen( + method, + classGen.getClassName(), + classGen.getConstantPool(), + classGen.getConstantPool().getConstantPool()) + .getInstructionList()) + .getStart(); + while (instructionHandle3 != null) { + label119: + { + if (instructionHandle2.getInstruction() instanceof PUTSTATIC + || instructionHandle2.getInstruction() instanceof PUTFIELD) { + if (instructionHandle2.getInstructionHandle() == null) { + instructionHandle = instructionHandle2; + break label119; + } + InstructionHandle instructionHandle4; + if ((instructionHandle4 = instructionHandle2.getInstructionHandle()).getInstruction() + instanceof LDC) { + LDC lDC = (LDC) instructionHandle4.getInstruction(); + Constant constant2; + if ((constant2 = classGen.getConstantPool().getConstant(lDC.getIndex())) + instanceof ConstantString) { + String bytes2 = + ((ConstantUtf8) + classGen + .getConstantPool() + .getConstant(((ConstantString) constant2).getStringIndex())) + .getBytes(); + values.add(bytes2); + } + } + } + instructionHandle = instructionHandle2; + } + instructionHandle3 = instructionHandle2 = instructionHandle.getInstructionHandle2(); + } + InstructionHandle instructionHandle5; + InstructionHandle instructionHandle6 = instructionHandle5 = instructionList.getStart(); + while (instructionHandle6 != null) { + InstructionHandle instructionHandle7; + if (!(instructionHandle5.getInstruction() instanceof LDC)) { + instructionHandle7 = instructionHandle5; + } else { + LDC lDC2 = (LDC) instructionHandle5.getInstruction(); + Constant constant3; + if (!((constant3 = classGen.getConstantPool().getConstant(lDC2.getIndex())) + instanceof ConstantString)) { + instructionHandle7 = instructionHandle5; + } else { + ConstantPoolGen constantPool = classGen.getConstantPool(); + int value5 = lDC2.produceStack(constantPool); + InstructionHandle instructionHandle22 = instructionHandle5.getInstructionHandle2(); + int value6 = 0; + while (true) { + if (instructionHandle22 != null) { + int value7 = instructionHandle22.getInstruction().produceStack(constantPool); + int value8 = instructionHandle22.getInstruction().consumeStack(constantPool); + if (value7 != -2) { + if (value8 == -2) { + instructionHandle7 = instructionHandle5; + break; + } + int value9; + if ((value9 = value5 - value8) > 0) { + value5 = value9 + value7; + instructionHandle22 = instructionHandle22.getInstructionHandle2(); + int value10 = value6++; + if (value10 > (byte) 33) { + instructionHandle7 = instructionHandle5; + break; + } + continue; + } + Instruction instruction; + if ((instruction = instructionHandle22.getInstruction()) instanceof IF_ACMPEQ + || instruction instanceof IF_ACMPNE) { + String bytes3 = + ((ConstantUtf8) + classGen + .getConstantPool() + .getConstant(((ConstantString) constant3).getStringIndex())) + .getBytes(); + instructionHandle7 = instructionHandle5; + values.add(bytes3); + break; + } + } + } + instructionHandle7 = instructionHandle5; + break; + } + } + } + instructionHandle6 = instructionHandle5 = instructionHandle7.getInstructionHandle2(); + } + } + } + } + + public static void update() { + values = new Vector(); + if (Configuration.getObfuscationOptions().getStringEncryptionIgnoredStrings() != null) { + BufferedReader bufferedReader; + try { + for (String text = + (bufferedReader = + new BufferedReader( + new FileReader( + Configuration.getObfuscationOptions() + .getStringEncryptionIgnoredStrings()))) + .readLine(); + text != null; + text = bufferedReader.readLine()) { + if (text.length() > 0) { + String text2; + if (text.startsWith("regex:")) { + text2 = text.substring(6); + } else { + text2 = text.replaceAll("\\.", "\\\\.").replaceAll("\\*", ".*"); + } + values.add(Pattern.compile(text2, 32)); + } + } + } catch (Exception exception) { + exception.printStackTrace(); + } + } + } + + public static void processCharacter(ClassGen classGen, String text, char value) { + InstructionFactory instructionFactory = new InstructionFactory(classGen); + ConstantPoolGen constantPool = classGen.getConstantPool(); + InstructionList instructionList = new InstructionList(); + MethodGen methodGen = + new MethodGen( + 9, + Type.STRING, + new Type[] {Type.STRING}, + new String[] {"s"}, + text, + classGen.getClassName(), + instructionList, + constantPool); + int value2 = constantPool.addClass("java.lang.String"); + int value3 = constantPool.addClass("[C"); + int value4 = constantPool.addUtf8("StackMap"); + ConstantPool constantPool2 = constantPool.getConstantPool(); + StackMapType[] stackMapTypes = new StackMapType[4]; + stackMapTypes[0] = new StackMapType((byte) 7, value2, constantPool2); + stackMapTypes[1] = new StackMapType((byte) 7, value3, constantPool2); + stackMapTypes[2] = new StackMapType((byte) 1, 0, constantPool2); + stackMapTypes[3] = new StackMapType((byte) 1, 0, constantPool2); + StackMapEntry stackMapEntry = + new StackMapEntry(27, 4, stackMapTypes, 0, new StackMapType[0], constantPool2); + StackMapEntry stackMapEntry2 = + new StackMapEntry( + 58, + 4, + new StackMapType[] { + new StackMapType((byte) 7, value2, constantPool2), + new StackMapType((byte) 7, value3, constantPool2), + new StackMapType((byte) 1, 0, constantPool2), + new StackMapType((byte) 1, 0, constantPool2) + }, + 0, + new StackMapType[0], + constantPool2); + StackMap stackMap = + new StackMap( + value4, 30, new StackMapEntry[] {stackMapEntry, stackMapEntry2}, constantPool2); + methodGen.addCodeAttribute(stackMap); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.OBJECT, 0)); + instructionList.getInstructionHandle( + instructionFactory.createInvoke( + "java.lang.String", "length", Type.INT, Type.NO_ARGS, (short) 182)); + instructionList.getInstructionHandle(instructionFactory.createNewArray(Type.CHAR, (short) 1)); + instructionList.getInstructionHandle(new PUSH(constantPool, 1)); + instructionList.getInstructionHandle(InstructionConstants.DUP); + instructionList.getInstructionHandle(InstructionConstants.POP2); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction(Type.OBJECT, 1)); + instructionList.getInstructionHandle(new PUSH(constantPool, value)); + instructionList.getInstructionHandle(new PUSH(constantPool, 1)); + instructionList.getInstructionHandle(InstructionConstants.DUP); + instructionList.getInstructionHandle(InstructionConstants.POP2); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction(Type.INT, 2)); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.OBJECT, 1)); + instructionList.getInstructionHandle(InstructionConstants.ARRAYLENGTH); + instructionList.getInstructionHandle(new PUSH(constantPool, 1)); + instructionList.getInstructionHandle(new PUSH(constantPool, 1)); + instructionList.getInstructionHandle(InstructionConstants.DUP); + instructionList.getInstructionHandle(InstructionConstants.POP2); + instructionList.getInstructionHandle(InstructionConstants.ISUB); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction(Type.INT, 3)); + BranchInstruction branchInstruction = + InstructionFactory.createBranchInstruction((short) 167, null); + instructionList.getBranchHandle(branchInstruction); + InstructionHandle instructionHandle = + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.OBJECT, 1)); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.INT, 3)); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.OBJECT, 0)); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.INT, 3)); + instructionList.getInstructionHandle( + instructionFactory.createInvoke( + "java.lang.String", "charAt", Type.CHAR, new Type[] {Type.INT}, (short) 182)); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.INT, 2)); + instructionList.getInstructionHandle(InstructionConstants.IXOR); + instructionList.getInstructionHandle(InstructionConstants.I2C); + instructionList.getInstructionHandle(new PUSH(constantPool, 1)); + instructionList.getInstructionHandle(InstructionConstants.DUP); + instructionList.getInstructionHandle(InstructionConstants.POP2); + instructionList.getInstructionHandle(InstructionConstants.CASTORE); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.INT, 2)); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.INT, 3)); + instructionList.getInstructionHandle(InstructionConstants.IXOR); + instructionList.getInstructionHandle(InstructionConstants.I2C); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction(Type.INT, 2)); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.INT, 2)); + instructionList.getInstructionHandle(new PUSH(constantPool, 63)); + instructionList.getInstructionHandle(new PUSH(constantPool, 1)); + instructionList.getInstructionHandle(InstructionConstants.DUP); + instructionList.getInstructionHandle(InstructionConstants.POP2); + instructionList.getInstructionHandle(InstructionConstants.IAND); + instructionList.getInstructionHandle(InstructionConstants.I2C); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction(Type.INT, 2)); + instructionList.getInstructionHandle(new IINC(3, -1)); + InstructionHandle instructionHandle2 = + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.INT, 3)); + instructionList.getBranchHandle( + InstructionFactory.createBranchInstruction((short) 156, instructionHandle)); + instructionList.getInstructionHandle(instructionFactory.createNew("java.lang.String")); + instructionList.getInstructionHandle(InstructionConstants.DUP); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.OBJECT, 1)); + instructionList.getInstructionHandle( + instructionFactory.createInvoke( + "java.lang.String", + "", + Type.VOID, + new Type[] {new ArrayType(Type.CHAR, 1)}, + (short) 183)); + instructionList.getInstructionHandle(InstructionFactory.createReturn(Type.OBJECT)); + branchInstruction.setTarget(instructionHandle2); + methodGen.update5(); + methodGen.update4(); + classGen.processMethod2(methodGen.getMethod()); + instructionList.update3(); + } + + public static boolean matchesText(String text) { + int value; + for (int value2 = value = values.size() - 1; value2 >= 0; value2 = --value) { + if (((Pattern) values.get(value)).matcher(text).matches()) { + return true; + } + } + return false; + } + + public static boolean matchesText2(Vector vector, String text) { + if ("00".equals(text)) { + return false; + } + if ("01".equals(text)) { + vector.add(InstructionConstants.ICONST_1); + } else if ("10".equals(text)) { + vector.add(InstructionConstants.ICONST_2); + } else if ("11".equals(text)) { + vector.add(InstructionConstants.ICONST_3); + } + return true; + } + + public static Vector createValues(int value) { + Vector vector = new Vector(); + String text; + String text2 = text = Integer.toBinaryString(value); + while (text2.length() < 7) { + text2 = text = "0" + text; + } + if (text.startsWith("0")) { + boolean matches; + if (matches = matchesText(vector, text.substring(1, 4))) { + vector.add(InstructionConstants.ICONST_3); + vector.add(InstructionConstants.ISHL); + } + if (matchesText(vector, text.substring(4, 7)) && matches) { + vector.add(InstructionConstants.IXOR); + } + return vector; + } else if (text.endsWith("0")) { + boolean matches2; + if (matches2 = matchesText(vector, text.substring(0, 3))) { + vector.add(InstructionConstants.ICONST_4); + vector.add(InstructionConstants.ISHL); + } + if (matchesText(vector, text.substring(3, 6)) && matches2) { + vector.add(InstructionConstants.ICONST_1); + vector.add(InstructionConstants.ISHL); + vector.add(InstructionConstants.IXOR); + } + return vector; + } else if (text.charAt(3) == '0') { + boolean matches3; + if (matches3 = matchesText(vector, text.substring(0, 3))) { + vector.add(InstructionConstants.ICONST_4); + vector.add(InstructionConstants.ISHL); + } + if (matchesText(vector, text.substring(4, 7)) && matches3) { + vector.add(InstructionConstants.IXOR); + } + return vector; + } else { + matchesText(vector, text.substring(0, 3)); + vector.add(InstructionConstants.ICONST_4); + vector.add(InstructionConstants.ISHL); + boolean matches4 = matchesText2(vector, text.substring(3, 5)); + if (matches4) { + vector.add(InstructionConstants.ICONST_2); + vector.add(InstructionConstants.ISHL); + } + if (matchesText2(vector, text.substring(5, 7))) { + vector.add(InstructionConstants.IXOR); + } + if (matches4) { + vector.add(InstructionConstants.IXOR); + } + return vector; + } + } + + public static String getText(ClassGen classGen) { + Attribute[] attributes; + if ((attributes = classGen.getAttributes()) == null) { + return "Unknown Source"; + } + int value; + for (int value2 = value = attributes.length - 1; value2 >= 0; value2 = --value) { + if (attributes[value] instanceof SourceFile) { + return ((SourceFile) attributes[value]).getText(); + } + } + return "Unknown Source"; + } + + public static void processClassGen(ClassGen classGen) { + Method[] methods; + int value; + for (int value2 = value = (methods = classGen.getMethods()).length - 1; + value2 >= 0; + value2 = --value) { + Method method; + if ((method = methods[value]).getCode() != null) { + InstructionHandle instructionHandle; + InstructionList instructionList; + InstructionHandle instructionHandle2 = + instructionHandle = + (instructionList = + MethodFactory.createMethodGen( + method, + classGen.getClassName(), + classGen.getConstantPool(), + classGen.getConstantPool().getConstantPool()) + .getInstructionList()) + .getStart(); + while (instructionHandle2 != null) { + InstructionHandle instructionHandle3; + if (!(instructionHandle.getInstruction() instanceof LDC)) { + instructionHandle3 = instructionHandle; + } else { + LDC lDC = (LDC) instructionHandle.getInstruction(); + if (!(classGen.getConstantPool().getConstant(lDC.getIndex()) + instanceof ConstantString)) { + instructionHandle3 = instructionHandle; + } else { + label145: + { + ConstantPoolGen constantPool = classGen.getConstantPool(); + int value3 = lDC.produceStack(constantPool); + InstructionHandle instructionHandle22 = instructionHandle.getInstructionHandle2(); + int value4 = 0; + while (instructionHandle22 != null) { + int value5 = instructionHandle22.getInstruction().produceStack(constantPool); + int value6 = instructionHandle22.getInstruction().consumeStack(constantPool); + if (value5 == -2) { + break; + } + if (value6 == -2) { + instructionHandle3 = instructionHandle; + break label145; + } + int value7; + if ((value7 = value3 - value6) <= 0) { + Instruction instruction; + if (!((instruction = instructionHandle22.getInstruction()) instanceof IF_ACMPEQ) + && !(instruction instanceof IF_ACMPNE)) { + break; + } + int value8; + do { + value8 = calculateCount(instructionHandle22); + } while ((instructionHandle22 = instructionHandle22.getInstructionHandle()) + != null + && value8 == -1); + String text = + "" + + classGen.getClassName() + + "." + + method.getText() + + "(" + + getText(classGen); + if (value8 != -1) { + text = "" + text + ":" + value8; + } + String text2 = "" + text + ")"; + Log.warn("Comparing strings using '==' operator at " + text2); + instructionHandle3 = instructionHandle; + break label145; + } + value3 = value7 + value5; + instructionHandle22 = instructionHandle22.getInstructionHandle2(); + int value9 = value4++; + if (value9 > (byte) 33) { + instructionHandle3 = instructionHandle; + break label145; + } + } + instructionHandle3 = instructionHandle; + } + } + } + instructionHandle2 = instructionHandle = instructionHandle3.getInstructionHandle2(); + } + InstructionHandle instructionHandle4; + InstructionHandle instructionHandle5 = instructionHandle4 = instructionList.getStart(); + while (instructionHandle5 != null) { + InstructionHandle instructionHandle6; + if (!(instructionHandle4.getInstruction() instanceof GETSTATIC) + && !(instructionHandle4.getInstruction() instanceof GETFIELD)) { + instructionHandle6 = instructionHandle4; + } else { + FieldInstruction fieldInstruction = + (FieldInstruction) instructionHandle4.getInstruction(); + ConstantPoolGen constantPool2 = classGen.getConstantPool(); + if (!((String) "Ljava/lang/String;").equals(fieldInstruction.getText3(constantPool2))) { + instructionHandle6 = instructionHandle4; + } else { + label142: + { + int value10 = fieldInstruction.produceStack(constantPool2); + InstructionHandle instructionHandle23 = instructionHandle4.getInstructionHandle2(); + int value11 = 0; + while (instructionHandle23 != null) { + int value12 = instructionHandle23.getInstruction().produceStack(constantPool2); + int value13 = instructionHandle23.getInstruction().consumeStack(constantPool2); + if (value12 == -2) { + break; + } + if (value13 == -2) { + instructionHandle6 = instructionHandle4; + break label142; + } + int value14; + if ((value14 = value10 - value13) <= 0) { + Instruction instruction2; + if (!((instruction2 = instructionHandle23.getInstruction()) + instanceof IF_ACMPEQ) + && !(instruction2 instanceof IF_ACMPNE)) { + break; + } + int value15; + do { + value15 = calculateCount(instructionHandle23); + } while ((instructionHandle23 = instructionHandle23.getInstructionHandle()) + != null + && value15 == -1); + String text3 = + "" + + classGen.getClassName() + + "." + + method.getText() + + "(" + + getText(classGen); + if (value15 != -1) { + text3 = "" + text3 + ":" + value15; + } + String text4 = "" + text3 + ")"; + Log.warn("Comparing strings using '==' operator at " + text4); + instructionHandle6 = instructionHandle4; + break label142; + } + value10 = value14 + value12; + instructionHandle23 = instructionHandle23.getInstructionHandle2(); + int value16 = value11++; + if (value16 > (byte) 33) { + instructionHandle6 = instructionHandle4; + break label142; + } + } + instructionHandle6 = instructionHandle4; + } + } + } + instructionHandle5 = instructionHandle4 = instructionHandle6.getInstructionHandle2(); + } + } + } + } + + public static int calculateCount(InstructionHandle instructionHandle) { + InstructionTargeter[] instructionTargeters; + if ((instructionTargeters = instructionHandle.getTargeters()) == null) { + return -1; + } + int value; + for (int value2 = value = instructionTargeters.length - 1; value2 >= 0; value2 = --value) { + if (instructionTargeters[value] instanceof LineNumberGen) { + return ((LineNumberGen) instructionTargeters[value]).getSourceLine(); + } + } + return -1; + } + + public static void processClassGen2(ClassGen classGen) { + int value; + Field[] fields; + for (int value2 = value = (fields = classGen.getFields()).length - 1; + value2 >= 0; + value2 = --value) { + Field field; + ConstantValue constantValue; + Constant constant; + if ((constantValue = (field = fields[value]).getConstantValue()) != null + && (constant = + classGen.getConstantPool().getConstant(constantValue.getConstantValueIndex())) + instanceof ConstantString + && field.isEnabled3()) { + if (!field.isEnabled11()) { + FieldGen fieldGen = new FieldGen(field, classGen.getConstantPool()); + fieldGen.cancelInitValue(); + classGen.replaceField(field, fieldGen.getField()); + } else { + Method method = null; + int value3; + Method[] methods; + for (int value4 = value3 = (methods = classGen.getMethods()).length - 1; + value4 >= 0; + value4 = --value3) { + Method method2 = methods[value3]; + if ("".equals(method2.getText())) { + method = method2; + break; + } + } + InstructionList instructionList = new InstructionList(); + instructionList.getInstructionHandle4(InstructionFactory.createReturn(Type.VOID)); + MethodGen methodGen; + ClassGen classGen2; + if (method != null) { + instructionList = + (methodGen = + MethodFactory.createMethodGen( + method, + classGen.getClassName(), + classGen.getConstantPool(), + classGen.getConstantPool().getConstantPool())) + .getInstructionList(); + classGen2 = classGen; + } else { + methodGen = + new MethodGen( + 8, + Type.VOID, + Type.NO_ARGS, + new String[0], + "", + classGen.getClassName(), + instructionList, + classGen.getConstantPool()); + classGen2 = classGen; + } + String bytes = + ((ConstantUtf8) + classGen2 + .getConstantPool() + .getConstant(((ConstantString) constant).getStringIndex())) + .getBytes(); + InstructionFactory instructionFactory = new InstructionFactory(classGen); + instructionList.getInstructionHandle4( + instructionFactory.createFieldAccess( + classGen.getClassName(), field.getText(), Type.STRING, (short) 179)); + instructionList.getInstructionHandle2(new PUSH(classGen.getConstantPool(), bytes)); + methodGen.update5(); + methodGen.update4(); + InstructionList instructionList2; + if (method != null) { + classGen.replaceMethod(method, methodGen.getMethod()); + instructionList2 = instructionList; + } else { + classGen.processMethod2(methodGen.getMethod()); + instructionList2 = instructionList; + } + instructionList2.update3(); + FieldGen fieldGen2 = new FieldGen(field, classGen.getConstantPool()); + fieldGen2.cancelInitValue(); + classGen.replaceField(field, fieldGen2.getField()); + } + } + } + } +} diff --git a/src/main/java/com/allatori/eclipse/AllatoriBuilder.java b/src/main/java/com/allatori/eclipse/AllatoriBuilder.java new file mode 100644 index 0000000..11fc79a --- /dev/null +++ b/src/main/java/com/allatori/eclipse/AllatoriBuilder.java @@ -0,0 +1,152 @@ +package com.allatori.eclipse; + +import com.allatori.Obfuscate; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.util.Map; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IncrementalProjectBuilder; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.Status; +import org.eclipse.jdt.core.IClasspathEntry; +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.JavaCore; + +public class AllatoriBuilder extends IncrementalProjectBuilder { + + public static final String TEXT = "com.allatori.eclipse"; + + public IProject[] build(int value, Map entries, IProgressMonitor progressMonitor) + throws CoreException { + this.getProject(); + switch (value) { + case 6: + this.processIProgressMonitor(progressMonitor); + case 7: + case 8: + case 9: + case 10: + default: + return null; + } + } + + public void processIProgressMonitor(IProgressMonitor progressMonitor) throws CoreException { + try { + String text = this.getProject().getLocation().toString(); + File file; + File file2; + if (!(file = new File(text + "/allatori.xml")).exists()) { + StringBuilder stringBuilder = new StringBuilder(); + StringBuilder stringBuilder2 = new StringBuilder(); + IClasspathEntry[] classpathEntrys; + IJavaProject javaProject; + int value = + (classpathEntrys = + (javaProject = JavaCore.create(this.getProject())).getResolvedClasspath(true)) + .length; + int value2; + for (int value3 = value2 = 0; value3 < value; value3 = ++value2) { + IClasspathEntry classpathEntry; + if ((classpathEntry = classpathEntrys[value2]).getEntryKind() == 3) { + if (classpathEntry.getOutputLocation() != null) { + String text2 = classpathEntry.getOutputLocation().removeFirstSegments(1).toString(); + stringBuilder.append(" \n"); + } + } else if (classpathEntry.getEntryKind() == 1) { + stringBuilder2.append( + " \n"); + } + } + if (javaProject.getOutputLocation() != null) { + String text3 = javaProject.getOutputLocation().removeFirstSegments(1).toString(); + stringBuilder.append(" \n"); + } + String text4 = + "\n \n" + + stringBuilder + + " \n\n" + + " \n" + + stringBuilder2 + + " \n\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n\n" + + " \n" + + "\n"; + BufferedWriter bufferedWriter = + new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8")); + file2 = file; + bufferedWriter.write(text4); + bufferedWriter.close(); + } else { + StringBuffer stringBuffer = new StringBuffer((int) file.length()); + int value4; + BufferedReader bufferedReader; + for (BufferedReader bufferedReader2 = + bufferedReader = + new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8")); + (value4 = bufferedReader2.read()) != -1; + bufferedReader2 = bufferedReader) { + stringBuffer.append((char) value4); + } + bufferedReader.close(); + String text5; + if ((text5 = stringBuffer.toString()).contains("${eclipse-")) { + StringBuilder stringBuilder3 = new StringBuilder(); + StringBuilder stringBuilder4 = new StringBuilder(); + IJavaProject javaProject2; + IClasspathEntry[] classpathEntrys2; + int value5 = + (classpathEntrys2 = + (javaProject2 = JavaCore.create(this.getProject())) + .getResolvedClasspath(true)) + .length; + int value6; + for (int value7 = value6 = 0; value7 < value5; value7 = ++value6) { + IClasspathEntry classpathEntry2; + if ((classpathEntry2 = classpathEntrys2[value6]).getEntryKind() == 3) { + if (classpathEntry2.getOutputLocation() != null) { + String text6 = + classpathEntry2.getOutputLocation().removeFirstSegments(1).toString(); + stringBuilder3.append( + " \n"); + } + } else if (classpathEntry2.getEntryKind() == 1) { + stringBuilder4.append( + " \n"); + } + } + if (javaProject2.getOutputLocation() != null) { + String text7 = javaProject2.getOutputLocation().removeFirstSegments(1).toString(); + stringBuilder3.append(" \n"); + } + String text8 = + text5 + .replace("${eclipse-input}", stringBuilder3) + .replace("${eclipse-classpath}", stringBuilder4); + file = new File(text + "/allatori-resolved.xml"); + BufferedWriter bufferedWriter2 = + new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8")); + bufferedWriter2.write(text8); + bufferedWriter2.close(); + } + file2 = file; + } + Obfuscate.run(file2); + } catch (Exception exception) { + exception.printStackTrace(); + throw new CoreException( + new Status(4, "com.allatori.eclipse", 0, exception.getMessage(), exception)); + } + } +} diff --git a/src/main/java/com/allatori/eclipse/AllatoriPropertyTester.java b/src/main/java/com/allatori/eclipse/AllatoriPropertyTester.java new file mode 100644 index 0000000..aeb81c1 --- /dev/null +++ b/src/main/java/com/allatori/eclipse/AllatoriPropertyTester.java @@ -0,0 +1,20 @@ +package com.allatori.eclipse; + +import org.eclipse.core.expressions.PropertyTester; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.Platform; + +public class AllatoriPropertyTester extends PropertyTester { + + public static final String TEXT = "isEnabled"; + + public boolean test(Object result, String text, Object[] results, Object result2) { + IProject project; + return "isEnabled".equals(text) + && (project = + (IProject) Platform.getAdapterManager().getAdapter(result, IProject.class)) + != null + ? MenuAddBuilder.matchesIProject(project) + : false; + } +} diff --git a/src/main/java/com/allatori/eclipse/MenuAddBuilder.java b/src/main/java/com/allatori/eclipse/MenuAddBuilder.java new file mode 100644 index 0000000..d4acbfd --- /dev/null +++ b/src/main/java/com/allatori/eclipse/MenuAddBuilder.java @@ -0,0 +1,84 @@ +package com.allatori.eclipse; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.IHandler; +import org.eclipse.core.resources.ICommand; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IProjectDescription; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.Platform; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.ui.handlers.HandlerUtil; + +public class MenuAddBuilder extends AbstractHandler implements IHandler { + + public static final boolean matchesIProject(IProject project) { + try { + ICommand[] commands; + int value = (commands = project.getDescription().getBuildSpec()).length; + int value2; + for (int value3 = value2 = 0; value3 < value; value3 = ++value2) { + ICommand command = commands[value2]; + if ("com.allatori.eclipse".equals(command.getBuilderName())) { + return true; + } + } + } catch (CoreException coreException) { + } + return false; + } + + public static IProject getIProject(ExecutionEvent executionEvent) { + ISelection selection; + if ((selection = HandlerUtil.getCurrentSelection(executionEvent)) + instanceof IStructuredSelection) { + Object firstElement = ((IStructuredSelection) selection).getFirstElement(); + return (IProject) Platform.getAdapterManager().getAdapter(firstElement, IProject.class); + } else { + return null; + } + } + + public Object execute(ExecutionEvent executionEvent) { + IProject project; + if ((project = getIProject(executionEvent)) != null) { + try { + if (matchesIProject(project)) { + return null; + } + ICommand command; + IProjectDescription projectDescription; + (command = (projectDescription = project.getDescription()).newCommand()) + .setBuilderName("com.allatori.eclipse"); + ArrayList values; + (values = new ArrayList()).addAll(Arrays.asList(projectDescription.getBuildSpec())); + int value = 0; + Iterator iterator2 = values.iterator(); + ArrayList values2; + label29: + { + for (Iterator iterator3 = iterator2; iterator3.hasNext(); iterator3 = iterator2) { + value++; + ICommand command2 = (ICommand) iterator2.next(); + if ("org.eclipse.jdt.core.javabuilder".equals(command2.getBuilderName())) { + values2 = values; + break label29; + } + } + values2 = values; + } + values2.add(value, command); + projectDescription.setBuildSpec((ICommand[]) values.toArray(new ICommand[values.size()])); + project.setDescription(projectDescription, null); + } catch (CoreException coreException) { + coreException.printStackTrace(); + } + } + return null; + } +} diff --git a/src/main/java/com/allatori/eclipse/MenuRemoveBuilder.java b/src/main/java/com/allatori/eclipse/MenuRemoveBuilder.java new file mode 100644 index 0000000..8b09e42 --- /dev/null +++ b/src/main/java/com/allatori/eclipse/MenuRemoveBuilder.java @@ -0,0 +1,39 @@ +package com.allatori.eclipse; + +import java.util.ArrayList; +import java.util.Arrays; +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.IHandler; +import org.eclipse.core.resources.ICommand; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IProjectDescription; +import org.eclipse.core.runtime.CoreException; + +public class MenuRemoveBuilder extends AbstractHandler implements IHandler { + + public Object execute(ExecutionEvent executionEvent) { + IProject project; + if ((project = MenuAddBuilder.getIProject(executionEvent)) != null) { + try { + IProjectDescription description = project.getDescription(); + ArrayList values; + (values = new ArrayList()).addAll(Arrays.asList(description.getBuildSpec())); + ICommand[] commands; + int value = (commands = description.getBuildSpec()).length; + int value2; + for (int value3 = value2 = 0; value3 < value; value3 = ++value2) { + ICommand command = commands[value2]; + if ("com.allatori.eclipse".equals(command.getBuilderName())) { + values.remove(command); + } + } + description.setBuildSpec((ICommand[]) values.toArray(new ICommand[values.size()])); + project.setDescription(description, null); + } catch (CoreException coreException) { + coreException.printStackTrace(); + } + } + return null; + } +} diff --git a/src/main/java/com/allatori/engine/ObfuscationAbortException.java b/src/main/java/com/allatori/engine/ObfuscationAbortException.java new file mode 100644 index 0000000..7ee5efb --- /dev/null +++ b/src/main/java/com/allatori/engine/ObfuscationAbortException.java @@ -0,0 +1,3 @@ +package com.allatori.engine; + +public class ObfuscationAbortException extends Exception {} diff --git a/src/main/java/com/allatori/engine/ObfuscationEngine.java b/src/main/java/com/allatori/engine/ObfuscationEngine.java new file mode 100644 index 0000000..c0ee1f1 --- /dev/null +++ b/src/main/java/com/allatori/engine/ObfuscationEngine.java @@ -0,0 +1,177 @@ +package com.allatori.engine; + +import com.allatori.bytecode.ConstantPoolEditor; +import com.allatori.config.Configuration; +import com.allatori.lib.bcel.classfile.Method; +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.lib.bcel.util.comparator.MethodComparator; +import com.allatori.model.ClassStorage; +import com.allatori.naming.NameRenamer; +import com.allatori.naming.generator.LowercaseConfusableNameGenerator; +import com.allatori.naming.generator.MixedConfusableNameGenerator; +import com.allatori.transform.ClassConstantPoolTransformer; +import com.allatori.transform.ClassTransformer; +import com.allatori.transform.ControlFlowTransformer; +import com.allatori.transform.DistributedStringEncryptionTransformer; +import com.allatori.transform.FieldAccessTransformer; +import com.allatori.transform.GlobalStringEncryptionTransformer; +import com.allatori.transform.HardwareIdTransformer; +import com.allatori.transform.MemberConstantPoolTransformer; +import com.allatori.transform.MemberReorderTransformer; +import com.allatori.transform.MemberVisibilityTransformer; +import com.allatori.transform.MethodAccessTransformer; +import com.allatori.transform.OptimizerTransformer; +import com.allatori.transform.RemoveFieldsTransformer; +import com.allatori.transform.RemoveMethodsTransformer; +import com.allatori.transform.StripAttributesTransformer; +import com.allatori.util.Log; +import java.util.Iterator; +import java.util.Vector; + +public class ObfuscationEngine { + + public ClassStorage classStorage; + + public boolean enabled; + + public void update() { + if (Configuration.getLogOptions().isText()) { + new HardwareIdTransformer(this.classStorage).transform(null); + } + Vector vector = new Vector(); + vector.add(new MemberVisibilityTransformer(this.classStorage)); + vector.add(new RemoveMethodsTransformer(this.classStorage)); + vector.add(new RemoveFieldsTransformer(this.classStorage)); + if (Configuration.getDebugInfoOptions().getText2() != null + && Configuration.getDebugInfoOptions().getText() != null) { + vector.add(new FieldAccessTransformer(this.classStorage)); + } + int stringEncryptionVersion = + Configuration.getObfuscationOptions().getStringEncryptionVersion(); + Configuration.getObfuscationOptions(); + if (stringEncryptionVersion == 1) { + DistributedStringEncryptionTransformer distributedStringEncryptionTransformer; + if ((distributedStringEncryptionTransformer = + new DistributedStringEncryptionTransformer(this.classStorage)) + .isEnabled()) { + vector.add(distributedStringEncryptionTransformer); + this.enabled = true; + } else { + vector.add(new GlobalStringEncryptionTransformer(this.classStorage)); + } + } else { + vector.add(new GlobalStringEncryptionTransformer(this.classStorage)); + } + vector.add(new MethodAccessTransformer(this.classStorage)); + vector.add(new ControlFlowTransformer(this.classStorage)); + vector.add(new OptimizerTransformer(this.classStorage)); + Iterator classesByName2 = this.classStorage.getClassesByName2(); + while (classesByName2.hasNext()) { + ClassGen classGen = (ClassGen) classesByName2.next(); + Iterator iterator2; + if (!Configuration.getIgnoreClassesOptions().matchesClassGen(this.classStorage, classGen)) { + for (Iterator iterator3 = iterator2 = vector.iterator(); + iterator3.hasNext(); + iterator3 = iterator2) { + ((ClassTransformer) iterator2.next()).transform(classGen); + } + } + } + Iterator iterator4; + Iterator iterator5 = iterator4 = vector.iterator(); + while (iterator5.hasNext()) { + ClassTransformer classTransformer = (ClassTransformer) iterator4.next(); + iterator5 = iterator4; + classTransformer.finish(); + } + } + + public ObfuscationEngine(ClassStorage classStorage2) { + super(); + this.enabled = false; + this.classStorage = classStorage2; + Method.setComparator(MethodComparator.getMethodComparator()); + MixedConfusableNameGenerator.processCount( + Integer.toBinaryString(classStorage2.getClassesByName()).length()); + LowercaseConfusableNameGenerator.processCount( + Integer.toBinaryString(classStorage2.getClassesByName()).length() + 1); + } + + public void update2() { + ConstantPoolEditor constantPoolEditor = new ConstantPoolEditor(this.classStorage); + Iterator classesByName2 = this.classStorage.getClassesByName2(); + while (classesByName2.hasNext()) { + ClassGen classGen = (ClassGen) classesByName2.next(); + if (!Configuration.getIgnoreClassesOptions().matchesClassGen(this.classStorage, classGen)) { + constantPoolEditor.processClassGen(classGen); + } + } + } + + public void obfuscate() { + Iterator classesByName2 = this.classStorage.getClassesByName2(); + ObfuscationEngine obfuscationEngine; + while (true) { + if (classesByName2.hasNext()) { + ClassGen classGen; + if ((classGen = (ClassGen) classesByName2.next()) + .getSuperclassName() + .startsWith("javax.microedition.")) { + Configuration.getObfuscationOptions().setEnabled(true); + obfuscationEngine = this; + break; + } + if (!classGen.getSuperclassName().startsWith("android.")) { + continue; + } + Configuration.getObfuscationOptions().setEnabled3(true); + obfuscationEngine = this; + break; + } + obfuscationEngine = this; + break; + } + obfuscationEngine.update(); + MemberReorderTransformer memberReorderTransformer = + new MemberReorderTransformer(this.classStorage); + Iterator classesByName22 = this.classStorage.getClassesByName2(); + while (classesByName22.hasNext()) { + ClassGen classGen2 = (ClassGen) classesByName22.next(); + if (!Configuration.getIgnoreClassesOptions().matchesClassGen(this.classStorage, classGen2)) { + memberReorderTransformer.transform(classGen2); + } + } + this.renameMembers(); + memberReorderTransformer.finish(); + ClassTransformer classTransformer; + if (this.enabled) { + classTransformer = new ClassConstantPoolTransformer(this.classStorage); + obfuscationEngine = this; + } else { + classTransformer = new MemberConstantPoolTransformer(this.classStorage); + obfuscationEngine = this; + } + Iterator classesByName23 = obfuscationEngine.classStorage.getClassesByName2(); + while (classesByName23.hasNext()) { + ClassGen classGen3 = (ClassGen) classesByName23.next(); + if (!Configuration.getIgnoreClassesOptions().matchesClassGen(this.classStorage, classGen3)) { + classTransformer.transform(classGen3); + } + } + classTransformer.finish(); + this.update2(); + new StripAttributesTransformer(this.classStorage).transform(null); + } + + public void renameMembers() { + try { + new NameRenamer(this.classStorage).rename(); + } catch (ObfuscationAbortException obfuscationAbortException) { + try { + Log.warn("Rerunning obfuscation due to un-renamed packages."); + new NameRenamer(this.classStorage).rename(); + } catch (ObfuscationAbortException obfuscationAbortException2) { + } + } + } +} diff --git a/src/main/java/com/allatori/engine/ObfuscationException.java b/src/main/java/com/allatori/engine/ObfuscationException.java new file mode 100644 index 0000000..582d9ad --- /dev/null +++ b/src/main/java/com/allatori/engine/ObfuscationException.java @@ -0,0 +1,8 @@ +package com.allatori.engine; + +public class ObfuscationException extends Exception { + + public ObfuscationException(String text) { + super(text); + } +} diff --git a/src/main/java/com/allatori/internal/BytecodeSupport.java b/src/main/java/com/allatori/internal/BytecodeSupport.java new file mode 100644 index 0000000..2c74317 --- /dev/null +++ b/src/main/java/com/allatori/internal/BytecodeSupport.java @@ -0,0 +1,8 @@ +package com.allatori.internal; + +import com.allatori.lib.bcel.generic.ClassGen; + +public interface BytecodeSupport { + + void processClassGen(ClassGen classGen); +} diff --git a/src/main/java/com/allatori/internal/NameSignatureInstructionSupport.java b/src/main/java/com/allatori/internal/NameSignatureInstructionSupport.java new file mode 100644 index 0000000..3f68723 --- /dev/null +++ b/src/main/java/com/allatori/internal/NameSignatureInstructionSupport.java @@ -0,0 +1,114 @@ +package com.allatori.internal; + +import com.allatori.lib.bcel.Constants; +import com.allatori.lib.bcel.ExceptionConstants; +import com.allatori.lib.bcel.classfile.Constant; +import com.allatori.lib.bcel.classfile.ConstantInvokeDynamic; +import com.allatori.lib.bcel.classfile.ConstantNameAndType; +import com.allatori.lib.bcel.classfile.ConstantPool; +import com.allatori.lib.bcel.generic.ConstantPoolGen; +import com.allatori.lib.bcel.generic.ExceptionThrower; +import com.allatori.lib.bcel.generic.NameSignatureInstruction; +import com.allatori.lib.bcel.generic.StackConsumer; +import com.allatori.lib.bcel.generic.StackProducer; +import com.allatori.lib.bcel.generic.Type; +import com.allatori.lib.bcel.generic.Visitor; +import com.allatori.lib.bcel.util.ByteSequence; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.StringTokenizer; + +public class NameSignatureInstructionSupport extends NameSignatureInstruction + implements ExceptionThrower, StackConsumer, StackProducer { + + public ConstantInvokeDynamic getConstantInvokeDynamic(ConstantPoolGen constantPoolGen) { + return (ConstantInvokeDynamic) constantPoolGen.getConstantPool().getConstant(this.index); + } + + public Type[] getTypes(ConstantPoolGen constantPoolGen) { + return Type.getArgumentTypes(this.getText(constantPoolGen)); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitExceptionThrower(this); + visitor.visitTypedInstruction(this); + visitor.visitStackConsumer(this); + visitor.visitStackProducer(this); + visitor.visitCPInstruction(this); + } + + @Override + public int produceStack(ConstantPoolGen constantPoolGen) { + return Type.calculateCount(this.getText(constantPoolGen)); + } + + @Override + public void initFromFile(ByteSequence byteSequence, boolean matches) throws IOException { + super.initFromFile(byteSequence, matches); + this.length = 5; + byteSequence.readUnsignedShort(); + } + + @Override + public Class[] getExceptions() { + Class[] classs = new Class[4 + ExceptionConstants.TYPES4.length]; + System.arraycopy(ExceptionConstants.TYPES4, 0, classs, 0, ExceptionConstants.TYPES4.length); + classs[ExceptionConstants.TYPES4.length + 3] = ExceptionConstants.TYPE9; + classs[ExceptionConstants.TYPES4.length + 2] = ExceptionConstants.TYPE7; + classs[ExceptionConstants.TYPES4.length + 1] = ExceptionConstants.TYPE14; + classs[ExceptionConstants.TYPES4.length] = ExceptionConstants.TYPE6; + return classs; + } + + @Override + public String toString(ConstantPool constantPool) { + Constant constant = constantPool.getConstant(this.index); + StringTokenizer stringTokenizer = new StringTokenizer(constantPool.constantToString(constant)); + return "" + + Constants.TEXTS8[this.opcode] + + " " + + stringTokenizer.nextToken().replace('.', '/') + + stringTokenizer.nextToken(); + } + + @Override + public int consumeStack(ConstantPoolGen constantPoolGen) { + return Type.calculateCount2(this.getText(constantPoolGen)); + } + + public Type getType2(ConstantPoolGen constantPoolGen) { + return Type.getReturnType(this.getText(constantPoolGen)); + } + + public NameSignatureInstructionSupport() {} + + @Override + public Type getType(ConstantPoolGen constantPoolGen) { + return this.getType2(constantPoolGen); + } + + public String getText3(ConstantPoolGen constantPoolGen) { + return this.getText2(constantPoolGen); + } + + @Override + public void dump(DataOutputStream dataOutputStream) throws IOException { + dataOutputStream.writeByte(this.opcode); + dataOutputStream.writeShort(this.index); + dataOutputStream.writeByte(0); + dataOutputStream.writeByte(0); + } + + @Override + public ConstantNameAndType getNameAndType(ConstantPoolGen constantPoolGen) { + ConstantPool constantPool = constantPoolGen.getConstantPool(); + ConstantInvokeDynamic constantInvokeDynamic = this.getConstantInvokeDynamic(constantPoolGen); + return (ConstantNameAndType) + constantPool.getConstant(constantInvokeDynamic.getBootstrapMethodAttrIndex2()); + } + + public NameSignatureInstructionSupport(short value, int value2) { + super(value, value2); + } +} diff --git a/src/main/java/com/allatori/internal/VerifierConstraintViolatedExceptionSupport.java b/src/main/java/com/allatori/internal/VerifierConstraintViolatedExceptionSupport.java new file mode 100644 index 0000000..6d1bfc5 --- /dev/null +++ b/src/main/java/com/allatori/internal/VerifierConstraintViolatedExceptionSupport.java @@ -0,0 +1,13 @@ +package com.allatori.internal; + +import com.allatori.lib.bcel.verifier.exc.VerifierConstraintViolatedException; + +public class VerifierConstraintViolatedExceptionSupport + extends VerifierConstraintViolatedException { + + public VerifierConstraintViolatedExceptionSupport(String text) { + super(text); + } + + public VerifierConstraintViolatedExceptionSupport() {} +} diff --git a/src/main/java/com/allatori/io/ClassStorageClassLoader.java b/src/main/java/com/allatori/io/ClassStorageClassLoader.java new file mode 100644 index 0000000..c850d1a --- /dev/null +++ b/src/main/java/com/allatori/io/ClassStorageClassLoader.java @@ -0,0 +1,81 @@ +package com.allatori.io; + +import com.allatori.config.Configuration; +import com.allatori.config.InputEntry; +import com.allatori.model.ClassStorage; +import com.allatori.util.Log; +import java.io.DataInputStream; +import java.io.IOException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Vector; +import java.util.jar.JarFile; +import java.util.zip.ZipEntry; + +public class ClassStorageClassLoader extends URLClassLoader { + + public ClassStorage classStorage; + + public byte[] createValues(JarFile jarFile, ZipEntry zipEntry) throws IOException { + byte[] values = new byte[(int) zipEntry.getSize()]; + DataInputStream dataInputStream; + (dataInputStream = new DataInputStream(jarFile.getInputStream(zipEntry))) + .readFully(values, 0, values.length); + dataInputStream.close(); + return values; + } + + public ClassStorageClassLoader(URL[] uRLs) { + super(uRLs, ClassStorageClassLoader.class.getClassLoader()); + } + + @Override + public Class findClass(String name) throws ClassNotFoundException, ClassNotFoundException { + try { + try { + if (classStorage.getClassGen(name) != null) return createType(name); + } catch (Exception ignored) { + } + return super.findClass(name); + } catch (ClassNotFoundException failure) { + try { + return createType(name); + } catch (Exception ignored) { + throw failure; + } + } + } + + public Class createType(String text) throws Exception { + try { + String text3 = text.replace('.', '/').concat(".class"); + Vector values3 = Configuration.getInputOptions().getValues3(); + int value; + for (int value2 = value = 0; value2 < values3.size(); value2 = ++value) { + InputEntry inputEntry = (InputEntry) values3.get(value); + JarFile jarFile = new JarFile(inputEntry.text2); + try { + ZipEntry zipEntry; + if ((zipEntry = jarFile.getEntry(text3)) != null) { + byte[] values = this.createValues(jarFile, zipEntry); + try { + return this.defineClass(text, values, 0, values.length); + } catch (IncompatibleClassChangeError incompatibleClassChangeError) { + Log.error("IncompatibleClassChangeError for class " + text); + throw incompatibleClassChangeError; + } + } + } finally { + jarFile.close(); + } + } + throw new Exception(); + } catch (Exception exception) { + throw exception; + } + } + + public void setClassStorage(ClassStorage classStorage2) { + this.classStorage = classStorage2; + } +} diff --git a/src/main/java/com/allatori/io/DirectoryClassReader.java b/src/main/java/com/allatori/io/DirectoryClassReader.java new file mode 100644 index 0000000..9250dad --- /dev/null +++ b/src/main/java/com/allatori/io/DirectoryClassReader.java @@ -0,0 +1,42 @@ +package com.allatori.io; + +import com.allatori.lib.bcel.classfile.ClassParser; +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.model.ClassStorage; +import com.allatori.util.Log; +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +public class DirectoryClassReader { + + public static ClassGen createClassGen(InputStream inputStream, String text) throws IOException { + ClassGen classGen = new ClassGen(new ClassParser(inputStream, text).parse()); + inputStream.close(); + return classGen; + } + + public static void processText(String text, ClassStorage classStorage, String text2) { + File[] files = new File(text).listFiles(); + int value; + for (int value2 = value = 0; value2 < files.length; value2 = ++value) { + File file; + if ((file = files[value]).isDirectory()) { + processText(file.getPath(), classStorage, text2); + } + if (file.getName().endsWith(".class")) { + try { + classStorage.processText( + createClassGen(new BufferedInputStream(new FileInputStream(file)), file.getName()), + text2); + } catch (Exception exception) { + if (!file.getName().endsWith("module-info.class")) { + Log.error("Cannot parse class " + file.getName()); + } + } + } + } + } +} diff --git a/src/main/java/com/allatori/io/DirectoryClassWriter.java b/src/main/java/com/allatori/io/DirectoryClassWriter.java new file mode 100644 index 0000000..244e93f --- /dev/null +++ b/src/main/java/com/allatori/io/DirectoryClassWriter.java @@ -0,0 +1,69 @@ +package com.allatori.io; + +import com.allatori.lib.asm.ClassWriter; +import com.allatori.util.Log; + +public class DirectoryClassWriter extends ClassWriter { + + public final ClassLoader classLoader; + + public final DirectoryWriter directoryWriter; + + public DirectoryClassWriter( + DirectoryWriter directoryWriter2, int value, ClassLoader classLoader2) { + super(value); + this.directoryWriter = directoryWriter2; + this.classLoader = classLoader2; + } + + @Override + public String getCommonSuperClass(String text, String text2) { + Class classValue; + Class classValue2; + try { + classValue2 = Class.forName(text.replace('/', '.'), false, this.classLoader); + classValue = Class.forName(text2.replace('/', '.'), false, this.classLoader); + } catch (ClassNotFoundException classNotFoundException) { + if (!DirectoryWriter.getValues(this.directoryWriter) + .contains(classNotFoundException.getMessage())) { + DirectoryWriter.getValues(this.directoryWriter).add(classNotFoundException.getMessage()); + Log.error("CLASS NOT FOUND: " + classNotFoundException.getMessage()); + Log.error(" ADD NEEDED JAR TO THE 'classpath' ELEMENT OF THE CONFIGURATION FILE."); + } + return "java/lang/Object"; + } catch (NoClassDefFoundError noClassDefFoundError) { + if (!DirectoryWriter.getValues(this.directoryWriter) + .contains(noClassDefFoundError.getMessage())) { + DirectoryWriter.getValues(this.directoryWriter).add(noClassDefFoundError.getMessage()); + Log.error("CLASS NOT FOUND: " + noClassDefFoundError.getMessage()); + Log.error(" ADD NEEDED JAR TO THE 'classpath' ELEMENT OF THE CONFIGURATION FILE."); + } + return "java/lang/Object"; + } catch (Exception exception) { + throw new RuntimeException(exception.toString()); + } catch (UnsupportedClassVersionError unsupportedClassVersionError) { + if (!DirectoryWriter.matchesDirectoryWriter(this.directoryWriter)) { + DirectoryWriter.matchesEnabled(this.directoryWriter, true); + Log.error( + "SOME CLASS(ES) CANNOT BE READ DUE TO JVM VERSION INCOMPATIBILITY: " + + unsupportedClassVersionError.toString()); + Log.error(" USE NEWER JVM VERSION TO RUN ALLATORI."); + } + return "java/lang/Object"; + } catch (Error error2) { + return "java/lang/Object"; + } + if (classValue2.isAssignableFrom(classValue)) { + return text; + } + if (classValue.isAssignableFrom(classValue2)) { + return text2; + } + if (!classValue2.isInterface() && !classValue.isInterface()) { + while (!(classValue2 = classValue2.getSuperclass()).isAssignableFrom(classValue)) {} + return classValue2.getName().replace('.', '/'); + } else { + return "java/lang/Object"; + } + } +} diff --git a/src/main/java/com/allatori/io/DirectoryWriter.java b/src/main/java/com/allatori/io/DirectoryWriter.java new file mode 100644 index 0000000..4312f73 --- /dev/null +++ b/src/main/java/com/allatori/io/DirectoryWriter.java @@ -0,0 +1,207 @@ +package com.allatori.io; + +import com.allatori.config.Configuration; +import com.allatori.lib.asm.ClassReader; +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.model.ClassStorage; +import com.allatori.util.FileUtils; +import com.allatori.util.Log; +import com.allatori.util.StreamUtils; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.HashSet; +import java.util.Vector; + +public class DirectoryWriter { + + public String text; + + public ClassStorage classStorage; + + public boolean enabled; + + public HashSet values = new HashSet(); + + public DirectoryWriter() { + this.enabled = false; + } + + public void processFile(ClassGen classGen, File file) + throws FileNotFoundException, ClassNotFoundException, IOException { + file.getParentFile().mkdirs(); + BufferedOutputStream bufferedOutputStream = + new BufferedOutputStream(new FileOutputStream(file)); + BufferedOutputStream bufferedOutputStream2; + if (classGen.getMajor() > 50) { + ResolvingClassLoader resolvingClassLoader = + new ResolvingClassLoader( + this.classStorage, Configuration.getMappingOptions().lookupTable); + ClassReader classReader = new ClassReader(classGen.getJavaClass().getBytes()); + DirectoryClassWriter directoryClassWriter = + new DirectoryClassWriter(this, 2, resolvingClassLoader); + bufferedOutputStream2 = bufferedOutputStream; + classReader.accept(directoryClassWriter, 4); + bufferedOutputStream.write(directoryClassWriter.toByteArray()); + } else { + bufferedOutputStream2 = bufferedOutputStream; + bufferedOutputStream.write(classGen.getJavaClass().getBytes()); + } + bufferedOutputStream2.close(); + } + + public void processText(File file, File file2, ClassStorage classStorage, String text2) + throws FileNotFoundException, IOException, ClassNotFoundException { + File[] files = file.listFiles(); + int value; + for (int value2 = value = 0; value2 < files.length; value2 = ++value) { + File file3; + if ((file3 = files[value]).isDirectory()) { + String text3; + if ((text3 = "" + text2 + "." + file3.getName()).startsWith(".")) { + text3 = text3.substring(1); + } + this.processText( + file3, new File(("" + file2.getPath() + "/" + file3.getName())), classStorage, text3); + } else if (file3.getName().endsWith(".class")) { + String name = file3.getName(); + String text4 = name.substring(0, name.length() - 6); + if (text2.length() > 0) { + text4 = "" + text2 + "." + text4; + } + ClassGen classGen; + if ((classGen = classStorage.getClassGen(text4)) != null + && !Configuration.getIgnoreClassesOptions().matchesClassGen(classStorage, classGen)) { + String className = classGen.getClassName(); + String text5 = "" + className.replace('.', '/') + ".class"; + this.processFile(classGen, new File(("" + this.text + "/" + text5))); + } else { + if (classGen == null) { + Log.warn( + "File " + + file3.getPath() + + " is copied with no modifications, as it is not in its package."); + } + new File(file2.getPath()).mkdirs(); + FileUtils.processFile(file3, new File(("" + file2.getPath() + "/" + file3.getName()))); + } + } else { + String text6 = "" + file2.getPath() + "/" + file3.getName(); + if (Configuration.getRenamingOptions() + .getResourceRenamingOptions() + .isUpdateResourceNamesEnabled()) { + if ((text6 = + "" + + this.text + + "/" + + StreamUtils.createText( + "", + new StringBuilder() + .insert(0, text2.replace('.', '/')) + .append('/') + .append(file3.getName()) + .toString())) + .contains("/")) { + new File(text6.substring(0, text6.lastIndexOf(47))).mkdirs(); + } + } else { + new File(file2.getPath()).mkdirs(); + } + if (Configuration.getRenamingOptions() + .getResourceRenamingOptions() + .matchesText(file3.getName())) { + FileInputStream fileInputStream = new FileInputStream(file3); + FileOutputStream fileOutputStream = new FileOutputStream(new File(text6)); + StreamUtils.processText( + fileInputStream, + fileOutputStream, + Configuration.getRenamingOptions() + .getResourceRenamingOptions() + .getText(file3.getName())); + fileInputStream.close(); + fileOutputStream.close(); + } else { + FileUtils.processFile(file3, new File(text6)); + } + } + } + Vector inputClasses = classStorage.getInputClasses(); + int value3; + for (int value4 = value3 = 0; value4 < inputClasses.size(); value4 = value3) { + ClassGen classGen2; + String className2 = (classGen2 = (ClassGen) inputClasses.get(value3)).getClassName(); + String text7 = "" + className2.replace('.', '/') + ".class"; + StringBuilder stringBuilder = + new StringBuilder().insert(0, this.text).append("/").append(text7); + value3++; + this.processFile(classGen2, new File(stringBuilder.toString())); + } + } + + public void processClassStorage(String text2, String text, ClassStorage classStorage2) + throws FileNotFoundException, IOException, ClassNotFoundException { + this.classStorage = classStorage2; + this.text = text; + if (text2.equals(text)) { + this.processText(new File(text2), classStorage2, ""); + } else { + this.processText(new File(text2), new File(text), classStorage2, ""); + } + } + + public static boolean matchesDirectoryWriter(DirectoryWriter directoryWriter) { + return directoryWriter.enabled; + } + + public void processText(File file, ClassStorage classStorage, String text2) + throws FileNotFoundException, ClassNotFoundException, IOException { + File[] files = file.listFiles(); + int value; + for (int value2 = value = 0; value2 < files.length; value2 = ++value) { + File file2; + if ((file2 = files[value]).isDirectory()) { + String text3; + if ((text3 = "" + text2 + "." + file2.getName()).startsWith(".")) { + text3 = text3.substring(1); + } + this.processText(file2, classStorage, text3); + } else if (file2.getName().endsWith(".class")) { + String name = file2.getName(); + String text4 = name.substring(0, name.length() - 6); + if (text2.length() > 0) { + text4 = "" + text2 + "." + text4; + } + ClassGen classGen; + if ((classGen = classStorage.getClassGen(text4)) != null + && !Configuration.getIgnoreClassesOptions().matchesClassGen(classStorage, classGen)) { + file2.delete(); + String className = classGen.getClassName(); + String text5 = "" + className.replace('.', '/') + ".class"; + this.processFile(classGen, new File(("" + this.text + "/" + text5))); + } + } + } + Vector inputClasses = classStorage.getInputClasses(); + int value3; + for (int value4 = value3 = 0; value4 < inputClasses.size(); value4 = value3) { + ClassGen classGen2; + String className2 = (classGen2 = (ClassGen) inputClasses.get(value3)).getClassName(); + String text6 = "" + className2.replace('.', '/') + ".class"; + StringBuilder stringBuilder = + new StringBuilder().insert(0, this.text).append("/").append(text6); + value3++; + this.processFile(classGen2, new File(stringBuilder.toString())); + } + } + + public static HashSet getValues(DirectoryWriter directoryWriter) { + return directoryWriter.values; + } + + public static boolean matchesEnabled(DirectoryWriter directoryWriter, boolean matches) { + return directoryWriter.enabled = matches; + } +} diff --git a/src/main/java/com/allatori/io/JarClassReader.java b/src/main/java/com/allatori/io/JarClassReader.java new file mode 100644 index 0000000..7178332 --- /dev/null +++ b/src/main/java/com/allatori/io/JarClassReader.java @@ -0,0 +1,43 @@ +package com.allatori.io; + +import com.allatori.lib.bcel.classfile.ClassParser; +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.model.ClassStorage; +import com.allatori.util.Log; +import java.io.IOException; +import java.io.InputStream; +import java.util.Enumeration; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; + +public class JarClassReader { + + public static ClassGen createClassGen(InputStream inputStream, String text) throws IOException { + ClassGen classGen = new ClassGen(new ClassParser(inputStream, text).parse()); + inputStream.close(); + return classGen; + } + + public static void processClassStorage(String text, ClassStorage classStorage) + throws IOException { + JarFile jarFile; + Enumeration enumeration = (jarFile = new JarFile(text)).entries(); + while (enumeration.hasMoreElements()) { + JarEntry jarEntry; + if (!(jarEntry = (JarEntry) enumeration.nextElement()).isDirectory() + && jarEntry.getName().endsWith(".class")) { + try { + classStorage.processText( + createClassGen(jarFile.getInputStream(jarEntry), jarEntry.getName()), + text, + jarEntry.getName()); + } catch (Exception exception) { + if (!jarEntry.getName().endsWith("module-info.class")) { + Log.error("Cannot parse class " + jarEntry.getName()); + } + } + } + } + jarFile.close(); + } +} diff --git a/src/main/java/com/allatori/io/JarClassWriter.java b/src/main/java/com/allatori/io/JarClassWriter.java new file mode 100644 index 0000000..6791ab6 --- /dev/null +++ b/src/main/java/com/allatori/io/JarClassWriter.java @@ -0,0 +1,66 @@ +package com.allatori.io; + +import com.allatori.lib.asm.ClassWriter; +import com.allatori.util.Log; + +public class JarClassWriter extends ClassWriter { + + public final JarWriter jarWriter; + + public final ClassLoader classLoader; + + @Override + public String getCommonSuperClass(String text, String text2) { + Class classValue; + Class classValue2; + try { + classValue = Class.forName(text.replace('/', '.'), false, this.classLoader); + classValue2 = Class.forName(text2.replace('/', '.'), false, this.classLoader); + } catch (ClassNotFoundException classNotFoundException) { + if (!JarWriter.getValues(this.jarWriter).contains(classNotFoundException.getMessage())) { + JarWriter.getValues(this.jarWriter).add(classNotFoundException.getMessage()); + Log.error("CLASS NOT FOUND: " + classNotFoundException.getMessage()); + Log.error(" ADD NEEDED JAR TO THE 'classpath' ELEMENT OF THE CONFIGURATION FILE."); + } + return "java/lang/Object"; + } catch (NoClassDefFoundError noClassDefFoundError) { + if (!JarWriter.getValues(this.jarWriter).contains(noClassDefFoundError.getMessage())) { + JarWriter.getValues(this.jarWriter).add(noClassDefFoundError.getMessage()); + Log.error("CLASS NOT FOUND: " + noClassDefFoundError.getMessage()); + Log.error(" ADD NEEDED JAR TO THE 'classpath' ELEMENT OF THE CONFIGURATION FILE."); + } + return "java/lang/Object"; + } catch (Exception exception) { + throw new RuntimeException(exception.toString()); + } catch (UnsupportedClassVersionError unsupportedClassVersionError) { + if (!JarWriter.matchesJarWriter(this.jarWriter)) { + JarWriter.matchesEnabled(this.jarWriter, true); + Log.error( + "SOME CLASS(ES) CANNOT BE READ DUE TO JVM VERSION INCOMPATIBILITY: " + + unsupportedClassVersionError.toString()); + Log.error(" USE NEWER JVM VERSION TO RUN ALLATORI."); + } + return "java/lang/Object"; + } catch (Error error2) { + return "java/lang/Object"; + } + if (classValue.isAssignableFrom(classValue2)) { + return text; + } + if (classValue2.isAssignableFrom(classValue)) { + return text2; + } + if (!classValue.isInterface() && !classValue2.isInterface()) { + while (!(classValue = classValue.getSuperclass()).isAssignableFrom(classValue2)) {} + return classValue.getName().replace('.', '/'); + } else { + return "java/lang/Object"; + } + } + + public JarClassWriter(JarWriter jarWriter2, int value, ClassLoader classLoader2) { + super(value); + this.jarWriter = jarWriter2; + this.classLoader = classLoader2; + } +} diff --git a/src/main/java/com/allatori/io/JarWriter.java b/src/main/java/com/allatori/io/JarWriter.java new file mode 100644 index 0000000..8339ed0 --- /dev/null +++ b/src/main/java/com/allatori/io/JarWriter.java @@ -0,0 +1,425 @@ +package com.allatori.io; + +import com.allatori.config.Configuration; +import com.allatori.config.InputJar; +import com.allatori.lib.asm.ClassReader; +import com.allatori.lib.bcel.classfile.ClassParser; +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.model.ClassStorage; +import com.allatori.util.Log; +import com.allatori.util.StreamUtils; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Field; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.Vector; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.jar.JarOutputStream; +import java.util.zip.CRC32; +import java.util.zip.ZipException; +import java.util.zip.ZipOutputStream; + +public class JarWriter { + + public final String text; + + public Hashtable entries; + + public boolean enabled; + + public ClassStorage classStorage; + + public Vector values; + + public HashSet values2; + + public JarWriter() { + super(); + this.text = ".tmp"; + this.values = new Vector(); + this.values2 = new HashSet(); + this.enabled = false; + } + + public String createText(JarFile jarFile, JarEntry jarEntry) { + try { + InputStream inputStream = jarFile.getInputStream(jarEntry); + ClassGen classGen = new ClassGen(new ClassParser(inputStream, jarEntry.getName()).parse()); + inputStream.close(); + return jarEntry + .getName() + .substring(0, jarEntry.getName().length() - classGen.getClassName().length() - 6); + } catch (Exception exception) { + return ""; + } + } + + public void processText(String[] texts, String text) throws FileNotFoundException, IOException { + byte[] values = new byte[262144]; + JarOutputStream jarOutputStream = + new JarOutputStream(new FileOutputStream(("" + text + ".tmp"))); + if (Configuration.getOutputOptions().getCompressionLevel() != -1) { + jarOutputStream.setLevel(Configuration.getOutputOptions().getCompressionLevel()); + } + Hashtable hashtable = new Hashtable(); + int value; + for (int value2 = value = 0; value2 < texts.length; value2 = value) { + JarFile jarFile; + Enumeration enumeration; + Enumeration enumeration2 = enumeration = (jarFile = new JarFile(texts[value])).entries(); + while (enumeration2.hasMoreElements()) { + JarEntry jarEntry = (JarEntry) enumeration.nextElement(); + if (hashtable.containsKey(jarEntry.getName())) { + enumeration2 = enumeration; + } else { + hashtable.put(jarEntry.getName(), ""); + InputStream inputStream = jarFile.getInputStream(jarEntry); + JarEntry jarEntry2 = new JarEntry(jarEntry.getName()); + jarOutputStream.putNextEntry(jarEntry2); + InputStream inputStream2 = inputStream; + int value3; + while ((value3 = inputStream2.read(values)) > 0) { + inputStream2 = inputStream; + jarOutputStream.write(values, 0, value3); + } + jarOutputStream.closeEntry(); + enumeration2 = enumeration; + } + } + JarFile jarFile2 = jarFile; + value++; + jarFile2.close(); + } + if (Configuration.getObfuscationOptions().isOutputJarCommentEnabled() + && !Configuration.getObfuscationOptions().isEnabled()) { + this.processJarOutputStream(jarOutputStream); + } + jarOutputStream.finish(); + jarOutputStream.close(); + this.processText(text + ".tmp", text); + } + + public static HashSet getValues(JarWriter jarWriter) { + return jarWriter.values2; + } + + public void processJarOutputStream(String text, JarOutputStream jarOutputStream) + throws IOException { + String text2 = ""; + label17: + while (true) { + String text3 = text; + while (text3.indexOf(47) > 0) { + text2 = "" + text2 + text.substring(0, text.indexOf(47) + 1); + text = text.substring(text.indexOf(47) + 1); + if (this.entries.containsKey(text2)) { + continue label17; + } + text3 = text; + this.entries.put(text2, ".tmp"); + jarOutputStream.putNextEntry(new JarEntry(text2)); + jarOutputStream.closeEntry(); + } + return; + } + } + + public void processText( + Vector vector, JarOutputStream jarOutputStream, ClassStorage classStorage, String text) + throws IOException { + int value; + for (int value2 = value = vector.size() - 1; value2 >= 0; value2 = value) { + ClassGen classGen = (ClassGen) vector.get(value); + value--; + this.processText(classGen, jarOutputStream, classStorage, text); + } + } + + public void processJarOutputStream(JarOutputStream jarOutputStream) { + if (Configuration.getObfuscationOptions().getOutputJarComment() != null) { + jarOutputStream.setComment(Configuration.getObfuscationOptions().getOutputJarComment()); + } + } + + public void processClassStorage(String text3, String text4, ClassStorage classStorage2) + throws IOException, FileNotFoundException, ZipException { + byte value; + this.classStorage = classStorage2; + this.entries = new Hashtable(); + byte[] values2 = new byte[262144]; + String text5 = ""; + JarFile jarFile = new JarFile(text3); + JarOutputStream jarOutputStream = + new JarOutputStream(new FileOutputStream(("" + text4 + ".tmp"))); + HashSet values3 = new HashSet(); + if (Configuration.getOutputOptions().isKeepDuplicateEntries()) { + try { + Field field; + if ((field = ZipOutputStream.class.getDeclaredField("names")) != null) { + field.setAccessible(true); + values3 = (HashSet) field.get(jarOutputStream); + } + } catch (RuntimeException runtimeException) { + if (runtimeException.getClass().getName().endsWith("InaccessibleObjectException")) { + Log.warn( + "Use '--add-opens java.base/java.util.zip=ALL-UNNAMED' Java launcher option to keep" + + " output jar duplicate entries"); + } + } catch (Exception exception) { + } + } + if (Configuration.getOutputOptions().getCompressionLevel() != -1) { + jarOutputStream.setLevel(Configuration.getOutputOptions().getCompressionLevel()); + } + Vector vector = new Vector(); + Enumeration enumeration = jarFile.entries(); + while (true) { + Enumeration enumeration2 = enumeration; + JarEntry jarEntry; + InputStream inputStream; + JarEntry jarEntry2; + while (true) { + if (!enumeration2.hasMoreElements()) { + this.processText(vector, jarOutputStream, classStorage2, text3); + this.processText(classStorage2.getInputClasses(), jarOutputStream, classStorage2, text3); + jarFile.close(); + if (Configuration.getObfuscationOptions().isOutputJarCommentEnabled() + && !Configuration.getObfuscationOptions().isEnabled()) { + this.processJarOutputStream(jarOutputStream); + } + jarOutputStream.finish(); + jarOutputStream.close(); + this.processText("" + text4 + ".tmp", text4); + return; + } + if ((jarEntry = (JarEntry) enumeration.nextElement()).isDirectory()) { + enumeration2 = enumeration; + } else { + String text6; + if (jarEntry.getName().endsWith(".class") + && (text6 = classStorage2.getText("" + text3 + '#' + jarEntry.getName())) != null) { + text5 = classStorage2.getText2("" + text3 + '#' + text6); + ClassGen classGen; + if ((classGen = classStorage2.getClassGen(text6)) != null + && !Configuration.getIgnoreClassesOptions() + .matchesClassGen(classStorage2, classGen)) { + enumeration2 = enumeration; + vector.add(classGen); + continue; + } + } + if (jarEntry.getName().equals("META-INF/INDEX.LIST")) { + enumeration2 = enumeration; + this.values.add(text4); + } else { + inputStream = jarFile.getInputStream(jarEntry); + String name = jarEntry.getName(); + if (Configuration.getRenamingOptions() + .getResourceRenamingOptions() + .isUpdateResourceNamesEnabled()) { + if (text5 == null && text3.endsWith(".war")) { + text5 = "WEB-INF/classes/"; + } + if (jarEntry.getName().startsWith("BOOT-INF/classes/")) { + text5 = "BOOT-INF/classes/"; + } + if (jarEntry.getName().startsWith("WEB-INF/classes/")) { + text5 = "WEB-INF/classes/"; + } + name = StreamUtils.createText(text5, jarEntry.getName()); + } + ClassGen classGen2; + if (Configuration.getLogOptions().isText() + && "com/license4j/resources/d.bfi".equals(jarEntry.getName()) + && (classGen2 = classStorage2.getClassGen("com.license4j.HardwareID")) != null) { + String text7; + if ((text7 = classGen2.getClassName()).indexOf(46) > 0) { + String text8 = text7.substring(0, text7.lastIndexOf(46) + 1).replace('.', '/'); + name = "" + text8 + Configuration.getLogOptions().getComLicense4jSupport(); + } else { + name = Configuration.getLogOptions().getComLicense4jSupport(); + } + } + jarEntry2 = new JarEntry(name); + if (!name.endsWith(".jar")) { + break; + } + byte value2 = 0; + Iterator iterator2 = Configuration.getInputOptions().getValues().iterator(); + while (true) { + if (!iterator2.hasNext()) { + value = value2; + break; + } + InputJar inputJar; + if ((inputJar = (InputJar) iterator2.next()).text.equals(text3) + && inputJar.text2.equals(jarEntry.getName())) { + if (jarEntry.getMethod() == 0) { + jarEntry2.setMethod(0); + } + File file = new File(inputJar.text); + jarEntry2.setSize(file.length()); + FileInputStream fileInputStream = new FileInputStream(file); + CRC32 cRC32 = new CRC32(); + FileInputStream fileInputStream2 = fileInputStream; + int value3; + while ((value3 = fileInputStream2.read(values2)) > 0) { + fileInputStream2 = fileInputStream; + cRC32.update(values2, 0, value3); + } + jarEntry2.setCrc(cRC32.getValue()); + fileInputStream.close(); + FileInputStream fileInputStream3 = new FileInputStream(file); + this.processJarOutputStream(jarEntry2.getName(), jarOutputStream); + try { + jarOutputStream.putNextEntry(jarEntry2); + if (Configuration.getOutputOptions().isKeepDuplicateEntries()) { + values3.clear(); + } + FileInputStream fileInputStream4 = fileInputStream3; + int value4; + while ((value4 = fileInputStream4.read(values2)) > 0) { + fileInputStream4 = fileInputStream3; + jarOutputStream.write(values2, 0, value4); + } + fileInputStream3.close(); + jarOutputStream.closeEntry(); + } catch (ZipException zipException) { + if (!zipException.getMessage().contains("duplicate")) { + throw zipException; + } + } + value = value2 = 1; + break; + } + } + if (value == 0 && jarEntry.getMethod() == 0) { + jarEntry2.setMethod(0); + jarEntry2.setSize(jarEntry.getSize()); + jarEntry2.setCrc(jarEntry.getCrc()); + } + if (value2 == 0) { + break; + } + enumeration2 = enumeration; + } + } + } + this.processJarOutputStream(jarEntry2.getName(), jarOutputStream); + try { + jarOutputStream.putNextEntry(jarEntry2); + if (Configuration.getOutputOptions().isKeepDuplicateEntries()) { + values3.clear(); + } + boolean matches = + Configuration.getRenamingOptions() + .getResourceRenamingOptions() + .matchesText(jarEntry.getName()); + InputStream inputStream2 = inputStream; + JarOutputStream jarOutputStream2; + if (matches) { + StreamUtils.processText( + inputStream, + jarOutputStream, + Configuration.getRenamingOptions() + .getResourceRenamingOptions() + .getText(jarEntry.getName())); + jarOutputStream2 = jarOutputStream; + } else { + int value5; + while ((value5 = inputStream2.read(values2)) > 0) { + inputStream2 = inputStream; + jarOutputStream.write(values2, 0, value5); + } + jarOutputStream2 = jarOutputStream; + } + jarOutputStream2.closeEntry(); + } catch (ZipException zipException2) { + if (!zipException2.getMessage().contains("duplicate")) { + throw zipException2; + } + } + } + } + + public static boolean matchesEnabled(JarWriter jarWriter, boolean matches) { + return jarWriter.enabled = matches; + } + + public static boolean matchesJarWriter(JarWriter jarWriter) { + return jarWriter.enabled; + } + + public void processText(String text, String text2) { + File file = new File(text); + File file2; + if ((file2 = new File(text2)).exists() && !file2.delete()) { + Log.warn("Cannot delete '" + file2.getPath() + "'"); + } + if (!file.renameTo(file2)) { + Log.warn("Cannot rename '" + file.getPath() + "' to '" + file2.getPath() + "'"); + Log.warn("Resulting file is '" + file.getPath() + "'"); + } + } + + public void update() { + int value; + for (int value2 = value = 0; value2 < this.values.size(); value2 = value) { + String text = (String) this.values.get(value); + value++; + this.processText(text); + } + } + + public void processText(String text) { + try { + File file = new File(text); + Runtime.getRuntime().exec("jar -i " + file.getName(), null, file.getParentFile()); + } catch (Exception exception) { + } + } + + public void processText( + ClassGen classGen, JarOutputStream jarOutputStream, ClassStorage classStorage, String text) + throws IOException { + String text2; + String text3 = text2 = classGen.getClassName(); + if (Configuration.getMappingOptions().lookupTable != null) { + text3 = Configuration.getMappingOptions().lookupTable.getText(text2); + } + String text4; + if ((text4 = classStorage.getText2("" + text + '#' + text3)) == null) { + text4 = ""; + } + String text5 = "" + text4 + text2.replace('.', '/') + ".class"; + JarEntry jarEntry = new JarEntry(text5); + this.processJarOutputStream(text5, jarOutputStream); + try { + jarOutputStream.putNextEntry(jarEntry); + JarOutputStream jarOutputStream2; + if (classGen.getMajor() > 50) { + ResolvingClassLoader resolvingClassLoader = + new ResolvingClassLoader(classStorage, Configuration.getMappingOptions().lookupTable); + ClassReader classReader = new ClassReader(classGen.getJavaClass().getBytes()); + JarClassWriter jarClassWriter = new JarClassWriter(this, 2, resolvingClassLoader); + jarOutputStream2 = jarOutputStream; + classReader.accept(jarClassWriter, 4); + jarOutputStream.write(jarClassWriter.toByteArray()); + } else { + jarOutputStream2 = jarOutputStream; + jarOutputStream.write(classGen.getJavaClass().getBytes()); + } + jarOutputStream2.closeEntry(); + } catch (Exception exception) { + exception.printStackTrace(); + } + } +} diff --git a/src/main/java/com/allatori/io/ResolvingClassLoader.java b/src/main/java/com/allatori/io/ResolvingClassLoader.java new file mode 100644 index 0000000..7182878 --- /dev/null +++ b/src/main/java/com/allatori/io/ResolvingClassLoader.java @@ -0,0 +1,41 @@ +package com.allatori.io; + +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.model.ClassStorage; +import com.allatori.util.LookupTable; +import java.net.URL; +import java.net.URLClassLoader; + +public class ResolvingClassLoader extends URLClassLoader { + + public ClassStorage classStorage; + + public LookupTable lookupTable; + + public ResolvingClassLoader(ClassStorage classStorage2, LookupTable lookupTable2) { + super(new URL[0], classStorage2.getClassLoader()); + this.classStorage = classStorage2; + this.lookupTable = lookupTable2; + } + + public Class getType(String text) { + ClassGen classGen = this.classStorage.getClassGen(text); + byte[] bytes = classGen.getJavaClass().getBytes(); + return this.defineClass(classGen.getClassName(), bytes, 0, bytes.length); + } + + @Override + public Class findClass(String text) throws ClassNotFoundException { + String text2 = text; + try { + if (this.lookupTable.matchesText(text2)) { + text2 = this.lookupTable.getText(text2); + } + if (this.classStorage.getClassGen(text2) != null) { + return this.getType(text2); + } + } catch (Exception exception) { + } + return super.findClass(text2); + } +} diff --git a/src/main/java/com/allatori/lib/asm/AnnotationVisitor.java b/src/main/java/com/allatori/lib/asm/AnnotationVisitor.java new file mode 100644 index 0000000..db0957d --- /dev/null +++ b/src/main/java/com/allatori/lib/asm/AnnotationVisitor.java @@ -0,0 +1,64 @@ +package com.allatori.lib.asm; + +public abstract class AnnotationVisitor { + + public final int api; + + public AnnotationVisitor av; + + public void visitEnum(String text, String text2, String text3) { + if (this.av != null) { + this.av.visitEnum(text, text2, text3); + } + } + + public AnnotationVisitor(int api, AnnotationVisitor annotationVisitor) { + super(); + if (api != 589824 + && api != 524288 + && api != 458752 + && api != 393216 + && api != 327680 + && api != 262144 + && api != 17432576) { + throw new IllegalArgumentException(stringConcat$0(api)); + } + if (api == 17432576) { + Constants.checkAsmExperimental(this); + } + this.api = api; + this.av = annotationVisitor; + } + + public static String stringConcat$0(int value) { + return "Unsupported api " + value; + } + + public AnnotationVisitor visitAnnotation(String text, String text2) { + return this.av != null ? this.av.visitAnnotation(text, text2) : null; + } + + public AnnotationVisitor(int value) { + this(value, null); + } + + public AnnotationVisitor visitArray(String text) { + return this.av != null ? this.av.visitArray(text) : null; + } + + public void visitEnd() { + if (this.av != null) { + this.av.visitEnd(); + } + } + + public AnnotationVisitor getDelegate() { + return this.av; + } + + public void visit(String text, Object result) { + if (this.av != null) { + this.av.visit(text, result); + } + } +} diff --git a/src/main/java/com/allatori/lib/asm/AnnotationWriter.java b/src/main/java/com/allatori/lib/asm/AnnotationWriter.java new file mode 100644 index 0000000..9e2eea8 --- /dev/null +++ b/src/main/java/com/allatori/lib/asm/AnnotationWriter.java @@ -0,0 +1,361 @@ +package com.allatori.lib.asm; + +public final class AnnotationWriter extends AnnotationVisitor { + + public int count; + + public AnnotationWriter nextAnnotation; + + public final AnnotationWriter previousAnnotation; + + public final int numElementValuePairsOffset; + + public final boolean useNamedValues; + + public final SymbolTable symbolTable; + + public final ByteVector annotation; + + @Override + public AnnotationVisitor visitAnnotation(String text, String text2) { + this.count++; + if (this.useNamedValues) { + this.annotation.putShort(this.symbolTable.addConstantUtf8(text)); + } + this.annotation.put12(64, this.symbolTable.addConstantUtf8(text2)).putShort(0); + return new AnnotationWriter(this.symbolTable, true, this.annotation, null); + } + + @Override + public void visit(String text, Object result) { + this.count++; + if (this.useNamedValues) { + this.annotation.putShort(this.symbolTable.addConstantUtf8(text)); + } + if (result instanceof String) { + this.annotation.put12(115, this.symbolTable.addConstantUtf8((String) result)); + } else if (result instanceof Byte) { + this.annotation.put12(66, this.symbolTable.getSymbol((Byte) result).index); + } else if (result instanceof Boolean) { + int value = (Boolean) result ? 1 : 0; + this.annotation.put12(90, this.symbolTable.getSymbol(value).index); + } else if (result instanceof Character) { + this.annotation.put12(67, this.symbolTable.getSymbol((Character) result).index); + } else if (result instanceof Short) { + this.annotation.put12(83, this.symbolTable.getSymbol((Short) result).index); + } else if (result instanceof Type) { + this.annotation.put12(99, this.symbolTable.addConstantUtf8(((Type) result).getDescriptor())); + } else { + if (result instanceof byte[]) { + byte[] values = (byte[]) result; + this.annotation.put12(91, values.length); + int value2 = values.length; + int value3; + for (int value4 = value3 = 0; value4 < value2; value4 = value3) { + byte value5 = values[value3]; + SymbolTable symbolTable2 = this.symbolTable; + ByteVector byteVector = this.annotation; + value3++; + byteVector.put12((byte) 66, symbolTable2.getSymbol(value5).index); + } + } else if (result instanceof boolean[]) { + boolean[] matchess = (boolean[]) result; + this.annotation.put12(91, matchess.length); + int value6 = matchess.length; + int value7; + for (int value8 = value7 = 0; value8 < value6; value8 = value7) { + boolean matches = matchess[value7]; + ByteVector byteVector2 = this.annotation; + Symbol symbol = this.symbolTable.getSymbol(matches ? 1 : 0); + value7++; + byteVector2.put12((byte) 90, symbol.index); + } + } else if (result instanceof short[]) { + short[] values2 = (short[]) result; + this.annotation.put12(91, values2.length); + int value9 = values2.length; + int value10; + for (int value11 = value10 = 0; value11 < value9; value11 = value10) { + short value12 = values2[value10]; + SymbolTable symbolTable3 = this.symbolTable; + ByteVector byteVector3 = this.annotation; + value10++; + byteVector3.put12((byte) 83, symbolTable3.getSymbol(value12).index); + } + } else if (result instanceof char[]) { + char[] values3 = (char[]) result; + this.annotation.put12(91, values3.length); + int value13 = values3.length; + int value14; + for (int value15 = value14 = 0; value15 < value13; value15 = value14) { + char value16 = values3[value14]; + SymbolTable symbolTable4 = this.symbolTable; + ByteVector byteVector4 = this.annotation; + value14++; + byteVector4.put12((byte) 67, symbolTable4.getSymbol(value16).index); + } + } else if (result instanceof int[]) { + int[] values4 = (int[]) result; + this.annotation.put12(91, values4.length); + int value17 = values4.length; + int value18; + for (int value19 = value18 = 0; value19 < value17; value19 = value18) { + int value20 = values4[value18]; + SymbolTable symbolTable5 = this.symbolTable; + ByteVector byteVector5 = this.annotation; + value18++; + byteVector5.put12((byte) 73, symbolTable5.getSymbol(value20).index); + } + } else if (result instanceof long[]) { + long[] values5 = (long[]) result; + this.annotation.put12(91, values5.length); + int value21 = values5.length; + int value22; + for (int value23 = value22 = 0; value23 < value21; value23 = value22) { + long value24 = values5[value22]; + SymbolTable symbolTable6 = this.symbolTable; + ByteVector byteVector6 = this.annotation; + value22++; + byteVector6.put12((byte) 74, symbolTable6.addConstantLong(value24).index); + } + } else if (result instanceof float[]) { + float[] values6 = (float[]) result; + this.annotation.put12(91, values6.length); + int value25 = values6.length; + int value26; + for (int value27 = value26 = 0; value27 < value25; value27 = value26) { + float value28 = values6[value26]; + SymbolTable symbolTable7 = this.symbolTable; + ByteVector byteVector7 = this.annotation; + value26++; + byteVector7.put12((byte) 70, symbolTable7.addConstantFloat(value28).index); + } + } else if (result instanceof double[]) { + double[] values7 = (double[]) result; + this.annotation.put12(91, values7.length); + int value29 = values7.length; + int value30; + for (int value31 = value30 = 0; value31 < value29; value31 = value30) { + double value32 = values7[value30]; + SymbolTable symbolTable8 = this.symbolTable; + ByteVector byteVector8 = this.annotation; + value30++; + byteVector8.put12((byte) 68, symbolTable8.addConstantDouble(value32).index); + } + } else { + Symbol symbol2 = this.symbolTable.addConstant(result); + this.annotation.put12(".s.IFJDCS".charAt(symbol2.tag), symbol2.index); + } + } + } + + public static void putParameterAnnotations( + int value, AnnotationWriter[] annotationWriters, int value2, ByteVector byteVector) { + int value3 = 1 + 2 * value2; + int value4; + for (int value5 = value4 = 0; value5 < value2; value5 = value4) { + AnnotationWriter annotationWriter = annotationWriters[value4]; + int value6 = + value3 + + (annotationWriter == null ? 0 : annotationWriter.computeAnnotationsSize(null) - 8); + value4++; + value3 = value6; + } + byteVector.putShort(value); + byteVector.putInt(value3); + byteVector.putByte(value2); + int value7 = 0; + for (int value8 = value7; value8 < value2; value8 = ++value7) { + AnnotationWriter annotationWriter2 = annotationWriters[value7]; + AnnotationWriter annotationWriter3 = null; + int value9 = 0; + AnnotationWriter annotationWriter4 = annotationWriter2; + while (annotationWriter4 != null) { + AnnotationWriter annotationWriter5 = annotationWriter2; + value9++; + annotationWriter5.visitEnd(); + annotationWriter3 = annotationWriter5; + annotationWriter4 = annotationWriter2 = annotationWriter5.previousAnnotation; + } + byteVector.putShort(value9); + AnnotationWriter annotationWriter6 = annotationWriter3; + for (AnnotationWriter annotationWriter7 = annotationWriter6; + annotationWriter7 != null; + annotationWriter7 = annotationWriter6) { + byteVector.putByteArray( + annotationWriter6.annotation.data, 0, annotationWriter6.annotation.length); + annotationWriter6 = annotationWriter6.nextAnnotation; + } + } + } + + public static void putAnnotations( + SymbolTable symbolTable, + AnnotationWriter annotationWriter, + AnnotationWriter annotationWriter2, + AnnotationWriter annotationWriter3, + AnnotationWriter annotationWriter4, + ByteVector byteVector) { + if (annotationWriter != null) { + annotationWriter.putAnnotations( + symbolTable.addConstantUtf8("RuntimeVisibleAnnotations"), byteVector); + } + if (annotationWriter2 != null) { + annotationWriter2.putAnnotations( + symbolTable.addConstantUtf8("RuntimeInvisibleAnnotations"), byteVector); + } + if (annotationWriter3 != null) { + annotationWriter3.putAnnotations( + symbolTable.addConstantUtf8("RuntimeVisibleTypeAnnotations"), byteVector); + } + if (annotationWriter4 != null) { + annotationWriter4.putAnnotations( + symbolTable.addConstantUtf8("RuntimeInvisibleTypeAnnotations"), byteVector); + } + } + + public static AnnotationWriter create( + SymbolTable symbolTable, String text, AnnotationWriter annotationWriter) { + ByteVector byteVector; + (byteVector = new ByteVector()).putShort(symbolTable.addConstantUtf8(text)).putShort(0); + return new AnnotationWriter(symbolTable, true, byteVector, annotationWriter); + } + + public int computeAnnotationsSize(String text) { + if (text != null) { + this.symbolTable.addConstantUtf8(text); + } + int value = 8; + AnnotationWriter annotationWriter; + for (AnnotationWriter annotationWriter2 = annotationWriter = this; + annotationWriter2 != null; + annotationWriter2 = annotationWriter = annotationWriter.previousAnnotation) { + value += annotationWriter.annotation.length; + } + return value; + } + + public static AnnotationWriter create( + SymbolTable symbolTable, + int value, + TypePath typePath, + String text, + AnnotationWriter annotationWriter) { + ByteVector byteVector = new ByteVector(); + TypeReference.putTarget(value, byteVector); + TypePath.put(typePath, byteVector); + byteVector.putShort(symbolTable.addConstantUtf8(text)).putShort(0); + return new AnnotationWriter(symbolTable, true, byteVector, annotationWriter); + } + + @Override + public void visitEnum(String text, String text2, String text3) { + this.count++; + if (this.useNamedValues) { + this.annotation.putShort(this.symbolTable.addConstantUtf8(text)); + } + this.annotation + .put12(101, this.symbolTable.addConstantUtf8(text2)) + .putShort(this.symbolTable.addConstantUtf8(text3)); + } + + public static int computeParameterAnnotationsSize( + String text, AnnotationWriter[] annotationWriters, int value) { + int value2 = 7 + 2 * value; + int value3; + for (int value4 = value3 = 0; value4 < value; value4 = value3) { + AnnotationWriter annotationWriter = annotationWriters[value3]; + int value5 = + value2 + + (annotationWriter == null ? 0 : annotationWriter.computeAnnotationsSize(text) - 8); + value3++; + value2 = value5; + } + return value2; + } + + @Override + public AnnotationVisitor visitArray(String text) { + this.count++; + if (this.useNamedValues) { + this.annotation.putShort(this.symbolTable.addConstantUtf8(text)); + } + this.annotation.put12(91, 0); + return new AnnotationWriter(this.symbolTable, false, this.annotation, null); + } + + public static int computeAnnotationsSize( + AnnotationWriter annotationWriter, + AnnotationWriter annotationWriter2, + AnnotationWriter annotationWriter3, + AnnotationWriter annotationWriter4) { + int value = 0; + if (annotationWriter != null) { + value += annotationWriter.computeAnnotationsSize("RuntimeVisibleAnnotations"); + } + if (annotationWriter2 != null) { + value += annotationWriter2.computeAnnotationsSize("RuntimeInvisibleAnnotations"); + } + if (annotationWriter3 != null) { + value += annotationWriter3.computeAnnotationsSize("RuntimeVisibleTypeAnnotations"); + } + if (annotationWriter4 != null) { + value += annotationWriter4.computeAnnotationsSize("RuntimeInvisibleTypeAnnotations"); + } + return value; + } + + public AnnotationWriter( + SymbolTable symbolTable2, + boolean useNamedValues, + ByteVector byteVector, + AnnotationWriter annotationWriter) { + super(589824); + this.symbolTable = symbolTable2; + this.useNamedValues = useNamedValues; + this.annotation = byteVector; + this.numElementValuePairsOffset = byteVector.length == 0 ? -1 : byteVector.length - 2; + if ((this.previousAnnotation = annotationWriter) != null) { + annotationWriter.nextAnnotation = this; + } + } + + public void putAnnotations(int value, ByteVector byteVector) { + int value2 = 2; + int value3 = 0; + AnnotationWriter annotationWriter = this; + AnnotationWriter annotationWriter2 = null; + AnnotationWriter annotationWriter3 = this; + while (annotationWriter3 != null) { + annotationWriter.visitEnd(); + ByteVector byteVector2 = annotationWriter.annotation; + int value4 = value2; + AnnotationWriter annotationWriter4 = annotationWriter; + AnnotationWriter annotationWriter5 = annotationWriter; + value3++; + value2 = value4 + byteVector2.length; + annotationWriter2 = annotationWriter4; + annotationWriter3 = annotationWriter = annotationWriter5.previousAnnotation; + } + byteVector.putShort(value); + byteVector.putInt(value2); + byteVector.putShort(value3); + AnnotationWriter annotationWriter6 = annotationWriter2; + for (AnnotationWriter annotationWriter7 = annotationWriter6; + annotationWriter7 != null; + annotationWriter7 = annotationWriter6) { + byteVector.putByteArray( + annotationWriter6.annotation.data, 0, annotationWriter6.annotation.length); + annotationWriter6 = annotationWriter6.nextAnnotation; + } + } + + @Override + public void visitEnd() { + if (this.numElementValuePairsOffset != -1) { + byte[] values = this.annotation.data; + values[this.numElementValuePairsOffset] = (byte) (this.count >>> 8); + values[this.numElementValuePairsOffset + 1] = (byte) this.count; + } + } +} diff --git a/src/main/java/com/allatori/lib/asm/Attribute$Set.java b/src/main/java/com/allatori/lib/asm/Attribute$Set.java new file mode 100644 index 0000000..20cc574 --- /dev/null +++ b/src/main/java/com/allatori/lib/asm/Attribute$Set.java @@ -0,0 +1,47 @@ +package com.allatori.lib.asm; + +public final class Attribute$Set { + + public static final int SIZE_INCREMENT = 6; + + public int size; + + public Attribute[] data = new Attribute[6]; + + public void addAttributes(Attribute attribute) { + Attribute attribute2; + for (Attribute attribute3 = attribute2 = attribute; + attribute3 != null; + attribute3 = attribute2 = attribute2.nextAttribute) { + if (!this.contains(attribute2)) { + this.add(attribute2); + } + } + } + + public Attribute[] toArray() { + Attribute[] attributes = new Attribute[this.size]; + System.arraycopy(this.data, 0, attributes, 0, this.size); + return attributes; + } + + public void add(Attribute attribute) { + if (this.size >= this.data.length) { + Attribute[] attributes; + Attribute[] attributes2 = attributes = new Attribute[this.data.length + 6]; + System.arraycopy(this.data, 0, attributes, 0, this.size); + this.data = attributes2; + } + this.data[this.size++] = attribute; + } + + public boolean contains(Attribute attribute) { + int value; + for (int value2 = value = 0; value2 < this.size; value2 = ++value) { + if (this.data[value].type.equals(attribute.type)) { + return true; + } + } + return false; + } +} diff --git a/src/main/java/com/allatori/lib/asm/Attribute.java b/src/main/java/com/allatori/lib/asm/Attribute.java new file mode 100644 index 0000000..4c27d43 --- /dev/null +++ b/src/main/java/com/allatori/lib/asm/Attribute.java @@ -0,0 +1,160 @@ +package com.allatori.lib.asm; + +public class Attribute { + + public Attribute nextAttribute; + + public final String type; + + public ByteVector cachedContent; + + public static Attribute read( + Attribute attribute, + ClassReader classReader, + int value, + int value2, + char[] values, + int value3, + Label[] labels) { + return attribute.read(classReader, value, value2, values, value3, labels); + } + + public final int computeAttributesSize(SymbolTable symbolTable) { + return this.computeAttributesSize(symbolTable, (byte[]) (Object) null, 0, -1, -1); + } + + public boolean isEnabled() { + return true; + } + + @Deprecated + public Label[] getLabels() { + return new Label[0]; + } + + public final void putAttributes(SymbolTable symbolTable, ByteVector byteVector) { + this.putAttributes(symbolTable, (byte[]) (Object) null, 0, -1, -1, byteVector); + } + + public static int computeAttributesSize(SymbolTable symbolTable, int value, int value2) { + int value3 = 0; + if ((value & 4096) != 0 && symbolTable.getCount() < 49) { + value3 += 6; + symbolTable.addConstantUtf8("Synthetic"); + } + if (value2 != 0) { + value3 += 8; + symbolTable.addConstantUtf8("Signature"); + } + if ((value & 131072) != 0) { + value3 += 6; + symbolTable.addConstantUtf8("Deprecated"); + } + return value3; + } + + public Attribute read( + ClassReader classReader, int value, int value2, char[] values, int value3, Label[] labels) { + Attribute attribute = new Attribute(this.type); + attribute.cachedContent = new ByteVector(classReader.readBytes(value, value2)); + return attribute; + } + + public final int getAttributeCount() { + int value = 0; + Attribute attribute; + Attribute attribute2 = attribute = this; + while (attribute2 != null) { + Attribute attribute3 = attribute.nextAttribute; + Attribute attribute4 = attribute.nextAttribute; + value++; + attribute2 = attribute4; + attribute = attribute3; + } + return value; + } + + public ByteVector getByteVector( + ClassWriter classWriter, byte[] values, int value, int value2, int value3) { + if (this.cachedContent == null) { + this.cachedContent = this.getByteVector2(classWriter, values, value, value2, value3); + } + return this.cachedContent; + } + + public boolean isEnabled2() { + return false; + } + + public final int computeAttributesSize( + SymbolTable symbolTable, byte[] values, int value, int value2, int value3) { + ClassWriter classWriter2 = symbolTable.classWriter; + int value4 = 0; + Attribute attribute; + for (Attribute attribute2 = attribute = this; attribute2 != null; attribute2 = attribute) { + symbolTable.addConstantUtf8(attribute.type); + value4 += 6 + attribute.getByteVector(classWriter2, values, value, value2, value3).length; + attribute = attribute.nextAttribute; + } + return value4; + } + + public ByteVector getByteVector2( + ClassWriter classWriter, byte[] values, int value, int value2, int value3) { + return this.cachedContent; + } + + public static byte[] write( + Attribute attribute, + ClassWriter classWriter, + byte[] values, + int value, + int value2, + int value3) { + ByteVector byteVector; + ByteVector byteVector2 = + byteVector = attribute.getByteVector(classWriter, values, value, value2, value3); + byte[] values2 = new byte[byteVector2.length]; + System.arraycopy(byteVector2.data, 0, values2, 0, byteVector.length); + return values2; + } + + public static void putAttributes( + SymbolTable symbolTable, int value, int value2, ByteVector byteVector) { + if ((value & 4096) != 0 && symbolTable.getCount() < 49) { + byteVector.putShort(symbolTable.addConstantUtf8("Synthetic")).putInt(0); + } + if (value2 != 0) { + byteVector.putShort(symbolTable.addConstantUtf8("Signature")).putInt(2).putShort(value2); + } + if ((value & 131072) != 0) { + byteVector.putShort(symbolTable.addConstantUtf8("Deprecated")).putInt(0); + } + } + + public static Label readLabel(ClassReader classReader, int value, Label[] labels) { + return classReader.createLabel(value, labels); + } + + public Attribute(String type) { + super(); + this.type = type; + } + + public final void putAttributes( + SymbolTable symbolTable, + byte[] values, + int value, + int value2, + int value3, + ByteVector byteVector) { + ClassWriter classWriter2 = symbolTable.classWriter; + Attribute attribute; + for (Attribute attribute2 = attribute = this; attribute2 != null; attribute2 = attribute) { + ByteVector byteVector2 = attribute.getByteVector(classWriter2, values, value, value2, value3); + byteVector.putShort(symbolTable.addConstantUtf8(attribute.type)).putInt(byteVector2.length); + byteVector.putByteArray(byteVector2.data, 0, byteVector2.length); + attribute = attribute.nextAttribute; + } + } +} diff --git a/src/main/java/com/allatori/lib/asm/ByteVector.java b/src/main/java/com/allatori/lib/asm/ByteVector.java new file mode 100644 index 0000000..a0b85c7 --- /dev/null +++ b/src/main/java/com/allatori/lib/asm/ByteVector.java @@ -0,0 +1,364 @@ +package com.allatori.lib.asm; + +public class ByteVector { + + public int length; + + public byte[] data = new byte[64]; + + public final ByteVector encodeUtf8(String text, int value, int value2) { + int size = text.length(); + int value3 = value; + int value4; + for (int value5 = value4 = value; value5 < size; value5 = ++value4) { + char value6; + if ((value6 = text.charAt(value4)) >= 1 && value6 <= 127) { + value3++; + } else if (value6 <= 2047) { + value3 += 2; + } else { + value3 += 3; + } + } + if (value3 > value2) { + throw new IllegalArgumentException("UTF8 string too large"); + } + int value7; + if ((value7 = this.length - value - 2) >= 0) { + this.data[value7] = (byte) (value3 >>> 8); + this.data[value7 + 1] = (byte) value3; + } + if (this.length + value3 - value > this.data.length) { + this.enlarge(value3 - value); + } + int value8 = this.length; + int value9; + for (int value10 = value9 = value; value10 < size; value10 = ++value9) { + char value11; + if ((value11 = text.charAt(value9)) >= 1 && value11 <= 127) { + byte value12 = (byte) value11; + int value13 = value8; + byte[] values = this.data; + value8++; + values[value13] = value12; + } else if (value11 <= 2047) { + char value14 = value11; + int value15 = value8; + byte[] values2 = this.data; + value8++; + values2[value15] = (byte) ((short) 192 | value14 >> (byte) 6 & 31); + char value16 = value11; + int value17 = value8; + byte[] values3 = this.data; + value8++; + values3[value17] = (byte) ((short) 128 | value16 & (byte) 63); + } else { + char value18 = value11; + int value19 = value8; + byte[] values4 = this.data; + value8++; + values4[value19] = (byte) ((short) 224 | value18 >> (byte) 12 & 15); + char value20 = value11; + int value21 = value8; + byte[] values5 = this.data; + value8++; + values5[value21] = (byte) ((short) 128 | value20 >> (byte) 6 & 63); + char value22 = value11; + int value23 = value8; + byte[] values6 = this.data; + value8++; + values6[value23] = (byte) ((short) 128 | value22 & (byte) 63); + } + } + this.length = value8; + return this; + } + + public int size() { + return this.length; + } + + public ByteVector putInt(int value) { + int value2 = this.length; + if (this.length + 4 > this.data.length) { + this.enlarge(4); + } + int value3 = value >>> 24; + int value4 = value2; + byte[] values = this.data; + byte[] values2 = this.data; + byte[] values3 = this.data; + byte[] values4 = this.data; + value2++; + values[value4] = (byte) value3; + int value5 = value >>> 16; + int value6 = value2; + value2++; + values2[value6] = (byte) value5; + int value7 = value >>> 8; + int value8 = value2; + value2++; + values3[value8] = (byte) value7; + byte value9 = (byte) value; + int value10 = value2; + value2++; + values4[value10] = value9; + this.length = value2; + return this; + } + + public final ByteVector put112(int value, int value2, int value3) { + int value4 = this.length; + if (this.length + 4 > this.data.length) { + this.enlarge(4); + } + byte value5 = (byte) value; + int value6 = value4; + byte[] values = this.data; + byte[] values2 = this.data; + byte[] values3 = this.data; + byte[] values4 = this.data; + value4++; + values[value6] = value5; + byte value7 = (byte) value2; + int value8 = value4; + value4++; + values2[value8] = value7; + int value9 = value3 >>> 8; + int value10 = value4; + value4++; + values3[value10] = (byte) value9; + byte value11 = (byte) value3; + int value12 = value4; + value4++; + values4[value12] = value11; + this.length = value4; + return this; + } + + public ByteVector putByteArray(byte[] values, int value, int length) { + if (this.length + length > this.data.length) { + this.enlarge(length); + } + if (values != null) { + System.arraycopy(values, value, this.data, this.length, length); + } + this.length += length; + return this; + } + + public final ByteVector put12(int value, int value2) { + int value3 = this.length; + if (this.length + 3 > this.data.length) { + this.enlarge(3); + } + byte value4 = (byte) value; + int value5 = value3; + byte[] values = this.data; + byte[] values2 = this.data; + byte[] values3 = this.data; + value3++; + values[value5] = value4; + int value6 = value2 >>> 8; + int value7 = value3; + value3++; + values2[value7] = (byte) value6; + byte value8 = (byte) value2; + int value9 = value3; + value3++; + values3[value9] = value8; + this.length = value3; + return this; + } + + public final ByteVector put11(int value, int value2) { + int value3 = this.length; + if (this.length + 2 > this.data.length) { + this.enlarge(2); + } + byte value4 = (byte) value; + int value5 = value3; + byte[] values = this.data; + byte[] values2 = this.data; + value3++; + values[value5] = value4; + byte value6 = (byte) value2; + int value7 = value3; + value3++; + values2[value7] = value6; + this.length = value3; + return this; + } + + public void enlarge(int value) { + if (this.length > this.data.length) { + throw new AssertionError("Internal error"); + } + int value2 = 2 * this.data.length; + int value3 = this.length + value; + byte[] values; + byte[] values2 = values = new byte[value2 > value3 ? value2 : value3]; + System.arraycopy(this.data, 0, values, 0, this.length); + this.data = values2; + } + + public ByteVector() {} + + public final ByteVector put122(int value, int value2, int value3) { + int value4 = this.length; + if (this.length + 5 > this.data.length) { + this.enlarge(5); + } + byte value5 = (byte) value; + int value6 = value4; + byte[] values = this.data; + byte[] values2 = this.data; + byte[] values3 = this.data; + byte[] values4 = this.data; + byte[] values5 = this.data; + value4++; + values[value6] = value5; + int value7 = value2 >>> 8; + int value8 = value4; + value4++; + values2[value8] = (byte) value7; + byte value9 = (byte) value2; + int value10 = value4; + value4++; + values3[value10] = value9; + int value11 = value3 >>> 8; + int value12 = value4; + value4++; + values4[value12] = (byte) value11; + byte value13 = (byte) value3; + int value14 = value4; + value4++; + values5[value14] = value13; + this.length = value4; + return this; + } + + public ByteVector(byte[] data) { + super(); + this.data = data; + this.length = data.length; + } + + public ByteVector putShort(int value) { + int value2 = this.length; + if (this.length + 2 > this.data.length) { + this.enlarge(2); + } + int value3 = value >>> 8; + int value4 = value2; + byte[] values = this.data; + byte[] values2 = this.data; + value2++; + values[value4] = (byte) value3; + byte value5 = (byte) value; + int value6 = value2; + value2++; + values2[value6] = value5; + this.length = value2; + return this; + } + + public ByteVector putLong(long value) { + int value2 = this.length; + if (this.length + 8 > this.data.length) { + this.enlarge(8); + } + byte[] values = this.data; + int value3 = (int) (value >>> 32); + int value4 = value3 >>> 24; + int value5 = value2; + value2++; + values[value5] = (byte) value4; + int value6 = value3 >>> 16; + int value7 = value2; + value2++; + values[value7] = (byte) value6; + int value8 = value3 >>> 8; + int value9 = value2; + value2++; + values[value9] = (byte) value8; + byte value10 = (byte) value3; + int value11 = value2; + value2++; + values[value11] = value10; + int value12 = (int) value; + int value13 = value12 >>> 24; + int value14 = value2; + value2++; + values[value14] = (byte) value13; + int value15 = value12 >>> 16; + int value16 = value2; + value2++; + values[value16] = (byte) value15; + int value17 = value12 >>> 8; + int value18 = value2; + value2++; + values[value18] = (byte) value17; + byte value19 = (byte) value12; + int value20 = value2; + value2++; + values[value20] = value19; + this.length = value2; + return this; + } + + public ByteVector putByte(int value) { + int value2 = this.length; + if (this.length + 1 > this.data.length) { + this.enlarge(1); + } + byte value3 = (byte) value; + int value4 = value2; + byte[] values = this.data; + value2++; + values[value4] = value3; + this.length = value2; + return this; + } + + public ByteVector(int value) { + super(); + this.data = new byte[value]; + } + + public ByteVector putUTF8(String text) { + int value; + if ((value = text.length()) > 65535) { + throw new IllegalArgumentException("UTF8 string too large"); + } + int value2 = this.length; + if (this.length + 2 + value > this.data.length) { + this.enlarge(2 + value); + } + byte[] values = this.data; + int value3 = value >>> 8; + int value4 = value2; + byte[] values2 = this.data; + byte[] values3 = this.data; + value2++; + values2[value4] = (byte) value3; + byte value5 = (byte) value; + int value6 = value2; + value2++; + values3[value6] = value5; + int value7; + for (int value8 = value7 = 0; value8 < value; value8 = ++value7) { + char value9; + if ((value9 = text.charAt(value7)) < 1 || value9 > 127) { + this.length = value2; + return this.encodeUtf8(text, value7, 65535); + } + byte value10 = (byte) value9; + int value11 = value2; + value2++; + values[value11] = value10; + } + this.length = value2; + return this; + } +} diff --git a/src/main/java/com/allatori/lib/asm/ClassReader.java b/src/main/java/com/allatori/lib/asm/ClassReader.java new file mode 100644 index 0000000..3f26bbb --- /dev/null +++ b/src/main/java/com/allatori/lib/asm/ClassReader.java @@ -0,0 +1,3620 @@ +package com.allatori.lib.asm; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; + +public class ClassReader { + + public final String[] constantUtf8Values; + + public final byte[] classFileBuffer; + + public final int[] cpInfoOffsets; + + public final int header; + + public static final int SKIP_FRAMES = 4; + + public final int maxStringLength; + + public static final int EXPAND_FRAMES = 8; + + public static final int SKIP_DEBUG = 2; + + public static final int INPUT_STREAM_DATA_CHUNK_SIZE = 4096; + + public static final int SKIP_CODE = 1; + + public final ConstantDynamic[] constantDynamicValues; + + public static final int EXPAND_ASM_INSNS = 256; + + public static final int MAX_BUFFER_SIZE = 1048576; + + public final int[] bootstrapMethodOffsets; + + @Deprecated public final byte[] b; + + public int readMethod(ClassVisitor classVisitor, Context context, int value) + throws ClassNotFoundException { + char[] values = context.charBuffer; + int value2 = value; + context.count7 = this.readUnsignedShort(value2); + context.text2 = this.getText2(value2 + 2, values); + int value3 = value2 + 4; + value2 += 6; + context.text = this.getText2(value3, values); + int value4 = 0; + int value5 = 0; + String[] texts = null; + byte value6 = 0; + int value7 = 0; + int value8 = 0; + int value9 = 0; + int value10 = 0; + int value11 = 0; + int value12 = 0; + int value13 = 0; + int value14 = 0; + int value15 = 0; + Attribute attribute = null; + int value16 = value2; + value2 += 2; + int value17 = this.readUnsignedShort(value16); + int value18 = value17; + while (true) { + int value19 = value18; + value17--; + if (value19 <= 0) { + String text3; + String[] texts2; + if (value7 == 0) { + text3 = null; + texts2 = texts; + } else { + text3 = this.getText4(value7, values); + texts2 = texts; + } + MethodVisitor methodVisitor; + if ((methodVisitor = + classVisitor.visitMethod( + context.count7, context.text2, context.text, text3, texts2)) + == null) { + return value2; + } + if (methodVisitor instanceof MethodWriter) { + MethodWriter methodWriter; + MethodWriter methodWriter2 = methodWriter = (MethodWriter) methodVisitor; + ClassReader classReader; + byte value20; + if ((context.count7 & 131072) != 0) { + value20 = 1; + classReader = this; + } else { + value20 = 0; + classReader = this; + } + if (methodWriter2.canCopyMethodAttributes( + this, + value6 != 0, + value20 != 0, + classReader.readUnsignedShort(value + 4), + value7, + value5)) { + methodWriter.processCount7(value, value2 - value); + return value2; + } + } + if (value15 != 0 && (context.count2 & 2) == 0) { + int value21 = this.readByte(value15); + int value22 = value15 + 1; + value18 = value21; + while (true) { + int value23 = value18; + value21--; + if (value23 <= 0) { + break; + } + String text22 = this.getText2(value22, values); + int value24 = value22; + MethodVisitor methodVisitor2 = methodVisitor; + value22 += 4; + methodVisitor2.visitParameter(text22, this.readUnsignedShort(value24 + (byte) 2)); + value18 = value21; + } + } + if (value14 != 0) { + AnnotationVisitor annotationVisitor = methodVisitor.visitAnnotationDefault(); + this.readElementValue(annotationVisitor, value14, null, values); + if (annotationVisitor != null) { + annotationVisitor.visitEnd(); + } + } + if (value8 != 0) { + int value25 = this.readUnsignedShort(value8); + int value26 = value8 + 2; + value18 = value25; + while (true) { + int value27 = value18; + value25--; + if (value27 <= 0) { + break; + } + int value28 = value26; + value26 += 2; + String text23 = this.getText2(value28, values); + value26 = + this.readElementValues( + methodVisitor.visitAnnotation(text23, true), value26, true, values); + value18 = value25; + } + } + if (value9 != 0) { + int value29 = this.readUnsignedShort(value9); + int value30 = value9 + 2; + value18 = value29; + while (true) { + int value31 = value18; + value29--; + if (value31 <= 0) { + break; + } + int value32 = value30; + value30 += 2; + String text24 = this.getText2(value32, values); + value30 = + this.readElementValues( + methodVisitor.visitAnnotation(text24, false), value30, true, values); + value18 = value29; + } + } + if (value12 != 0) { + int value33 = this.readUnsignedShort(value12); + int value34 = value12 + 2; + value18 = value33; + while (true) { + int value35 = value18; + value33--; + if (value35 <= 0) { + break; + } + int value36; + int value37 = value36 = this.readTypeAnnotationTarget(context, value34); + value36 += 2; + String text25 = this.getText2(value37, values); + value34 = + this.readElementValues( + methodVisitor.createAnnotationVisitor2( + context.count6, context.currentTypeAnnotationTargetPath, text25, true), + value36, + true, + values); + value18 = value33; + } + } + if (value13 != 0) { + int value38 = this.readUnsignedShort(value13); + int value39 = value13 + 2; + value18 = value38; + while (true) { + int value40 = value18; + value38--; + if (value40 <= 0) { + break; + } + int value41; + int value42 = value41 = this.readTypeAnnotationTarget(context, value39); + value41 += 2; + String text26 = this.getText2(value42, values); + value39 = + this.readElementValues( + methodVisitor.createAnnotationVisitor2( + context.count6, context.currentTypeAnnotationTargetPath, text26, false), + value41, + true, + values); + value18 = value38; + } + } + if (value10 != 0) { + this.readParameterAnnotations(methodVisitor, context, value10, true); + } + if (value11 != 0) { + this.readParameterAnnotations(methodVisitor, context, value11, false); + } + Attribute attribute2 = attribute; + while (attribute2 != null) { + Attribute attribute3 = attribute.nextAttribute; + attribute.nextAttribute = null; + attribute2 = attribute3; + methodVisitor.visitAttribute(attribute); + attribute = attribute3; + } + if (value4 != 0) { + methodVisitor.visitCode(); + this.readCode(methodVisitor, context, value4); + } + methodVisitor.visitEnd(); + return value2; + } + int value43; + label175: + { + String text27 = this.getText2(value2, values); + int value44 = value2; + value2 += 6; + value43 = this.readInt(value44 + (byte) 2); + if ("Code".equals(text27)) { + if ((context.count2 & 1) == 0) { + value4 = value2; + value18 = value2; + break label175; + } + } else if ("Exceptions".equals(text27)) { + value5 = value2; + texts = new String[this.readUnsignedShort(value5)]; + int value45 = value5 + 2; + int value46; + for (int value47 = value46 = 0; value47 < texts.length; value47 = ++value46) { + String text5 = this.getText5(value45, values); + int value48 = value46; + String[] texts3 = texts; + value45 += 2; + texts3[value48] = text5; + } + } else { + if ("Signature".equals(text27)) { + value7 = this.readUnsignedShort(value2); + value18 = value2; + break label175; + } + if ("Deprecated".equals(text27)) { + value18 = value2; + context.count7 |= 131072; + break label175; + } + if ("RuntimeVisibleAnnotations".equals(text27)) { + value8 = value2; + value18 = value2; + break label175; + } + if ("RuntimeVisibleTypeAnnotations".equals(text27)) { + value12 = value2; + value18 = value2; + break label175; + } + if ("AnnotationDefault".equals(text27)) { + value14 = value2; + value18 = value2; + break label175; + } + if ("Synthetic".equals(text27)) { + value6 = 1; + value18 = value2; + context.count7 |= 4096; + break label175; + } + if ("RuntimeInvisibleAnnotations".equals(text27)) { + value9 = value2; + value18 = value2; + break label175; + } + if ("RuntimeInvisibleTypeAnnotations".equals(text27)) { + value13 = value2; + value18 = value2; + break label175; + } + if ("RuntimeVisibleParameterAnnotations".equals(text27)) { + value10 = value2; + value18 = value2; + break label175; + } + if ("RuntimeInvisibleParameterAnnotations".equals(text27)) { + value11 = value2; + value18 = value2; + break label175; + } + if ("MethodParameters".equals(text27)) { + value15 = value2; + value18 = value2; + break label175; + } + Attribute attribute4 = + this.readAttribute( + context.attributePrototypes, text27, value2, value43, values, -1, null); + attribute4.nextAttribute = attribute; + attribute = attribute4; + } + value18 = value2; + } + value2 = value18 + value43; + value18 = value17; + } + } + + public static byte[] readStream(InputStream inputStream, boolean matches) throws IOException { + if (inputStream == null) { + throw new IOException("Class not found"); + } + int value = computeBufferSize(inputStream); + byte[] values; + try { + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + label125: + { + byte[] values2; + try { + byte[] values3 = new byte[value]; + int value2 = 0; + InputStream inputStream2 = inputStream; + int value3; + while ((value3 = inputStream2.read(values3, 0, value)) != -1) { + value2++; + inputStream2 = inputStream; + byteArrayOutputStream.write(values3, 0, value3); + } + byteArrayOutputStream.flush(); + if (value2 == 1) { + values = values3; + break label125; + } + values2 = byteArrayOutputStream.toByteArray(); + } catch (Throwable throwable) { + try { + byteArrayOutputStream.close(); + } catch (Throwable throwable2) { + throw throwable; + } + throw throwable; + } + byteArrayOutputStream.close(); + return values2; + } + byteArrayOutputStream.close(); + } finally { + if (matches) { + inputStream.close(); + } + } + return values; + } + + public int getHeader() { + return this.readUnsignedShort(this.header); + } + + public String readUtf(int value, int value2, char[] values) { + int value3 = value; + int value4 = value + value2; + int value5 = 0; + byte[] values2 = this.classFileBuffer; + while (value3 < value4) { + byte value6; + byte value7 = value6 = values2[value3]; + value3++; + if ((value7 & 128) == 0) { + int value8 = value6 & 127; + int value9 = value5; + value5++; + values[value9] = (char) value8; + } else if ((value6 & 224) == 192) { + int value10 = value6 & 31; + int value11 = value5; + value5++; + int value12 = value10 << 6; + int value13 = values2[value3] & 63; + value3++; + values[value11] = (char) (value12 + value13); + } else { + int value14 = value6 & 15; + int value15 = value5; + value5++; + int value16 = value14 << 12; + int value17 = values2[value3] & 63; + int value18 = value16; + value3++; + value16 = value18 + (value17 << 6); + int value19 = values2[value3] & 63; + int value20 = value16; + value3++; + values[value15] = (char) (value20 + value19); + } + } + return new String(values, 0, value5); + } + + public int[] readBootstrapMethodsAttribute(int value) { + char[] values = new char[value]; + int value2; + int value3; + for (int value4 = value2 = this.readUnsignedShort((value3 = this.calculateCount()) - 2); + value4 > 0; + value4 = value2) { + String text2 = this.getText2(value3, values); + int value5 = value3; + value3 += 6; + int value6 = this.readInt(value5 + (byte) 2); + if ("BootstrapMethods".equals(text2)) { + int[] values2 = new int[this.readUnsignedShort(value3)]; + int value7 = value3 + 2; + int value8; + for (value4 = value8 = 0; value4 < values2.length; value4 = value8) { + value4 = values2[value8] = value7; + int value9 = this.readUnsignedShort(value7 + 2) * 2; + int value10 = value4; + value8++; + value7 = value10 + (byte) 4 + value9; + } + return values2; + } + int value11 = value3; + value2--; + value3 = value11 + value6; + } + throw new IllegalArgumentException(); + } + + public final int calculateCount() { + int value; + int value2 = value = this.header + 8 + this.readUnsignedShort(this.header + 6) * 2; + value += 2; + int value3 = this.readUnsignedShort(value2); + while (true) { + int value4 = value3--; + if (value4 <= 0) { + int value5 = value; + value += 2; + int value6 = this.readUnsignedShort(value5); + while (true) { + int value7 = value6--; + if (value7 <= 0) { + return value + 2; + } + int value8 = value; + value += 8; + int value9 = this.readUnsignedShort(value8 + (byte) 6); + int value10 = value9; + while (true) { + int value11 = value10; + value9--; + if (value11 <= 0) { + break; + } + value += 6 + this.readInt(value + 2); + value10 = value9; + } + } + } + int value12 = value; + value += 8; + int value13 = this.readUnsignedShort(value12 + (byte) 6); + int value14 = value13; + while (true) { + int value15 = value14; + value13--; + if (value15 <= 0) { + break; + } + value += 6 + this.readInt(value + 2); + value14 = value13; + } + } + } + + public byte[] readBytes(int value, int value2) { + byte[] values = new byte[value2]; + System.arraycopy(this.classFileBuffer, value, values, 0, value2); + return values; + } + + public Label getLabel(int value, Label[] labels) { + Label label = this.createLabel(value, labels); + label.value3 = (short) (label.value3 & -2); + return label; + } + + public int readUnsignedShort(int value) { + byte[] values = this.classFileBuffer; + return (this.classFileBuffer[value] & 0xFF) << 8 | values[value + 1] & 0xFF; + } + + public void accept(ClassVisitor classVisitor, int value) throws ClassNotFoundException { + this.accept(classVisitor, new Attribute[0], value); + } + + public int readField(ClassVisitor classVisitor, Context context, int value) { + char[] values = context.charBuffer; + int value2 = value; + int value3 = this.readUnsignedShort(value2); + String text2 = this.getText2(value2 + 2, values); + int value4 = value2 + 4; + value2 += 6; + String text22 = this.getText2(value4, values); + Object result = null; + String text = null; + int value5 = 0; + int value6 = 0; + int value7 = 0; + int value8 = 0; + Attribute attribute = null; + int value9 = value2; + value2 += 2; + int value10 = this.readUnsignedShort(value9); + int value11 = value10; + while (true) { + int value12 = value11; + value10--; + if (value12 <= 0) { + FieldVisitor fieldVisitor; + if ((fieldVisitor = classVisitor.visitField(value3, text2, text22, text, result)) == null) { + return value2; + } + if (value5 != 0) { + int value13 = this.readUnsignedShort(value5); + int value14 = value5 + 2; + value11 = value13; + while (true) { + int value15 = value11; + value13--; + if (value15 <= 0) { + break; + } + int value16 = value14; + value14 += 2; + String text23 = this.getText2(value16, values); + value14 = + this.readElementValues( + fieldVisitor.visitAnnotation(text23, true), value14, true, values); + value11 = value13; + } + } + if (value6 != 0) { + int value17 = this.readUnsignedShort(value6); + int value18 = value6 + 2; + value11 = value17; + while (true) { + int value19 = value11; + value17--; + if (value19 <= 0) { + break; + } + int value20 = value18; + value18 += 2; + String text24 = this.getText2(value20, values); + value18 = + this.readElementValues( + fieldVisitor.visitAnnotation(text24, false), value18, true, values); + value11 = value17; + } + } + if (value7 != 0) { + int value21 = this.readUnsignedShort(value7); + int value22 = value7 + 2; + value11 = value21; + while (true) { + int value23 = value11; + value21--; + if (value23 <= 0) { + break; + } + int value24; + int value25 = value24 = this.readTypeAnnotationTarget(context, value22); + value24 += 2; + String text25 = this.getText2(value25, values); + value22 = + this.readElementValues( + fieldVisitor.visitTypeAnnotation( + context.count6, context.currentTypeAnnotationTargetPath, text25, true), + value24, + true, + values); + value11 = value21; + } + } + if (value8 != 0) { + int value26 = this.readUnsignedShort(value8); + int value27 = value8 + 2; + value11 = value26; + while (true) { + int value28 = value11; + value26--; + if (value28 <= 0) { + break; + } + int value29; + int value30 = value29 = this.readTypeAnnotationTarget(context, value27); + value29 += 2; + String text26 = this.getText2(value30, values); + value27 = + this.readElementValues( + fieldVisitor.visitTypeAnnotation( + context.count6, context.currentTypeAnnotationTargetPath, text26, false), + value29, + true, + values); + value11 = value26; + } + } + Attribute attribute2 = attribute; + while (attribute2 != null) { + Attribute attribute3 = attribute.nextAttribute; + attribute.nextAttribute = null; + attribute2 = attribute3; + fieldVisitor.visitAttribute(attribute); + attribute = attribute3; + } + fieldVisitor.visitEnd(); + return value2; + } + String text27 = this.getText2(value2, values); + int value31 = value2; + value2 += 6; + int value32 = this.readInt(value31 + (byte) 2); + if ("ConstantValue".equals(text27)) { + int value33; + result = + (value33 = this.readUnsignedShort(value2)) == 0 + ? null + : this.readConst(value33, values); + value11 = value2; + } else if ("Signature".equals(text27)) { + text = this.getText2(value2, values); + value11 = value2; + } else if ("Deprecated".equals(text27)) { + value3 |= 131072; + value11 = value2; + } else if ("Synthetic".equals(text27)) { + value3 |= 4096; + value11 = value2; + } else if ("RuntimeVisibleAnnotations".equals(text27)) { + value5 = value2; + value11 = value2; + } else if ("RuntimeVisibleTypeAnnotations".equals(text27)) { + value7 = value2; + value11 = value2; + } else if ("RuntimeInvisibleAnnotations".equals(text27)) { + value6 = value2; + value11 = value2; + } else if ("RuntimeInvisibleTypeAnnotations".equals(text27)) { + value8 = value2; + value11 = value2; + } else { + Attribute attribute4 = + this.readAttribute( + context.attributePrototypes, text27, value2, value32, values, -1, null); + attribute4.nextAttribute = attribute; + attribute = attribute4; + value11 = value2; + } + value2 = value11 + value32; + value11 = value10; + } + } + + public int readVerificationTypeInfo( + int value, Object[] results, int value2, char[] values, Label[] labels) { + int value3 = value; + int value4 = this.classFileBuffer[value3] & 255; + value3++; + switch (value4) { + case 0: + results[value2] = Opcodes.INTEGER3; + return value3; + case 1: + results[value2] = Opcodes.INTEGER4; + return value3; + case 2: + results[value2] = Opcodes.INTEGER6; + return value3; + case 3: + results[value2] = Opcodes.INTEGER; + return value3; + case 4: + results[value2] = Opcodes.INTEGER5; + return value3; + case 5: + results[value2] = Opcodes.INTEGER2; + return value3; + case 6: + results[value2] = Opcodes.INTEGER7; + return value3; + case 7: + String text5 = this.getText5(value3, values); + value3 += 2; + results[value2] = text5; + return value3; + case 8: + Label label = this.getLabel(this.readUnsignedShort(value3), labels); + value3 += 2; + results[value2] = label; + return value3; + default: + throw new IllegalArgumentException(); + } + } + + public int readStackMapFrame(int value, boolean matches, boolean matches2, Context context) { + int value2 = value; + char[] values3 = context.charBuffer; + Label[] labels = context.labels3; + int value3; + Context context2; + if (matches) { + int value4 = this.classFileBuffer[value2] & 255; + value2++; + context2 = context; + value3 = value4; + } else { + value3 = 255; + context2 = context; + context.count = -1; + } + context2.count5 = 0; + int value5; + if (value3 < 64) { + value5 = value3; + context2 = context; + context.count3 = 3; + context.count4 = 0; + } else if (value3 < 128) { + value5 = value3 - 64; + context2 = context; + value2 = this.readVerificationTypeInfo(value2, context.values2, 0, values3, labels); + context.count3 = 4; + context.count4 = 1; + } else { + if (value3 < 247) { + throw new IllegalArgumentException(); + } + int value6 = value2; + value2 += 2; + value5 = this.readUnsignedShort(value6); + if (value3 == 247) { + context2 = context; + value2 = this.readVerificationTypeInfo(value2, context.values2, 0, values3, labels); + context.count3 = 4; + context.count4 = 1; + } else if (value3 >= 248 && value3 < 251) { + context2 = context; + context.count3 = 2; + context.count5 = 251 - value3; + context.count8 = context.count8 - context.count5; + context.count4 = 0; + } else if (value3 == 251) { + context2 = context; + context.count3 = 3; + context.count4 = 0; + } else if (value3 < 255) { + int value7 = matches2 ? context.count8 : 0; + int value8; + for (int value9 = value8 = value3 - 251; value9 > 0; value9 = value8) { + int value10 = value7; + Object[] results = context.values; + int value11 = value2; + value8--; + int value12 = this.readVerificationTypeInfo(value11, results, value10, values3, labels); + value7++; + value2 = value12; + } + context2 = context; + context.count3 = 1; + context.count5 = value3 - 251; + context.count8 = context.count8 + context.count5; + context.count4 = 0; + } else { + int value13 = this.readUnsignedShort(value2); + byte value14 = 0; + value2 += 2; + int value15 = value14; + context.count3 = 0; + context.count5 = value13; + context.count8 = value13; + for (int value16 = value14; value15 < value13; value15 = value16) { + int value17 = value16; + Object[] results2 = context.values; + int value18 = value2; + value16++; + value2 = this.readVerificationTypeInfo(value18, results2, value17, values3, labels); + } + int value19 = this.readUnsignedShort(value2); + byte value20 = 0; + value2 += 2; + int value21 = value20; + context.count4 = value19; + for (int value22 = value20; value21 < value19; value21 = value22) { + int value23 = value22; + Object[] results3 = context.values2; + int value24 = value2; + value22++; + value2 = this.readVerificationTypeInfo(value24, results3, value23, values3, labels); + } + context2 = context; + } + } + context2.count += value5 + 1; + this.getLabel(context.count, labels); + return value2; + } + + public int readRecordComponent(ClassVisitor classVisitor, Context context, int value) { + char[] values = context.charBuffer; + int value2 = value; + String text2 = this.getText2(value2, values); + int value3 = value2 + 2; + value2 += 4; + String text22 = this.getText2(value3, values); + String text = null; + int value4 = 0; + int value5 = 0; + int value6 = 0; + int value7 = 0; + Attribute attribute = null; + int value8 = value2; + value2 += 2; + int value9 = this.readUnsignedShort(value8); + int value10 = value9; + while (true) { + int value11 = value10; + value9--; + if (value11 <= 0) { + RecordComponentVisitor recordComponentVisitor; + if ((recordComponentVisitor = classVisitor.visitRecordComponent(text2, text22, text)) + == null) { + return value2; + } + if (value4 != 0) { + int value12 = this.readUnsignedShort(value4); + int value13 = value4 + 2; + value10 = value12; + while (true) { + int value14 = value10; + value12--; + if (value14 <= 0) { + break; + } + int value15 = value13; + value13 += 2; + String text23 = this.getText2(value15, values); + value13 = + this.readElementValues( + recordComponentVisitor.visitAnnotation(text23, true), value13, true, values); + value10 = value12; + } + } + if (value5 != 0) { + int value16 = this.readUnsignedShort(value5); + int value17 = value5 + 2; + value10 = value16; + while (true) { + int value18 = value10; + value16--; + if (value18 <= 0) { + break; + } + int value19 = value17; + value17 += 2; + String text24 = this.getText2(value19, values); + value17 = + this.readElementValues( + recordComponentVisitor.visitAnnotation(text24, false), value17, true, values); + value10 = value16; + } + } + if (value6 != 0) { + int value20 = this.readUnsignedShort(value6); + int value21 = value6 + 2; + value10 = value20; + while (true) { + int value22 = value10; + value20--; + if (value22 <= 0) { + break; + } + int value23; + int value24 = value23 = this.readTypeAnnotationTarget(context, value21); + value23 += 2; + String text25 = this.getText2(value24, values); + value21 = + this.readElementValues( + recordComponentVisitor.visitTypeAnnotation( + context.count6, context.currentTypeAnnotationTargetPath, text25, true), + value23, + true, + values); + value10 = value20; + } + } + if (value7 != 0) { + int value25 = this.readUnsignedShort(value7); + int value26 = value7 + 2; + value10 = value25; + while (true) { + int value27 = value10; + value25--; + if (value27 <= 0) { + break; + } + int value28; + int value29 = value28 = this.readTypeAnnotationTarget(context, value26); + value28 += 2; + String text26 = this.getText2(value29, values); + value26 = + this.readElementValues( + recordComponentVisitor.visitTypeAnnotation( + context.count6, context.currentTypeAnnotationTargetPath, text26, false), + value28, + true, + values); + value10 = value25; + } + } + Attribute attribute2 = attribute; + while (attribute2 != null) { + Attribute attribute3 = attribute.nextAttribute; + attribute.nextAttribute = null; + attribute2 = attribute3; + recordComponentVisitor.visitAttribute(attribute); + attribute = attribute3; + } + recordComponentVisitor.visitEnd(); + return value2; + } + String text27 = this.getText2(value2, values); + int value30 = value2; + value2 += 6; + int value31 = this.readInt(value30 + (byte) 2); + if ("Signature".equals(text27)) { + text = this.getText2(value2, values); + value10 = value2; + } else if ("RuntimeVisibleAnnotations".equals(text27)) { + value4 = value2; + value10 = value2; + } else if ("RuntimeVisibleTypeAnnotations".equals(text27)) { + value6 = value2; + value10 = value2; + } else if ("RuntimeInvisibleAnnotations".equals(text27)) { + value5 = value2; + value10 = value2; + } else if ("RuntimeInvisibleTypeAnnotations".equals(text27)) { + value7 = value2; + value10 = value2; + } else { + Attribute attribute4 = + this.readAttribute( + context.attributePrototypes, text27, value2, value31, values, -1, null); + attribute4.nextAttribute = attribute; + attribute = attribute4; + value10 = value2; + } + value2 = value10 + value31; + value10 = value9; + } + } + + public Object readConst(int value, char[] values) { + int value2 = this.cpInfoOffsets[value]; + switch (this.classFileBuffer[value2 - 1]) { + case 3: + return this.readInt(value2); + case 4: + return Float.intBitsToFloat(this.readInt(value2)); + case 5: + return this.readLong(value2); + case 6: + return Double.longBitsToDouble(this.readLong(value2)); + case 7: + return Type.getObjectType(this.getText2(value2, values)); + case 8: + return this.getText2(value2, values); + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + default: + throw new IllegalArgumentException(); + case 15: + int value3 = this.readByte(value2); + int value4 = this.cpInfoOffsets[this.readUnsignedShort(value2 + 1)]; + int value5 = this.cpInfoOffsets[this.readUnsignedShort(value4 + 2)]; + String text5 = this.getText5(value4, values); + String text2 = this.getText2(value5, values); + String text22 = this.getText2(value5 + 2, values); + int value6 = this.classFileBuffer[value4 - 1] == 11 ? 1 : 0; + return new Handle(value3, text5, text2, text22, (value6 != 0)); + case 16: + return Type.getMethodType(this.getText2(value2, values)); + case 17: + return this.readConstantDynamic(value, values); + } + } + + public String getText(int value, char[] values) { + return this.getText6(value, values); + } + + public Attribute readAttribute( + Attribute[] attributes, + String text, + int value, + int value2, + char[] values, + int value3, + Label[] labels) { + if (value2 > this.classFileBuffer.length - value) { + throw new IllegalArgumentException(); + } + int value4 = attributes.length; + int value5; + for (int value6 = value5 = 0; value6 < value4; value6 = ++value5) { + Attribute attribute; + if ((attribute = attributes[value5]).type.equals(text)) { + return attribute.read(this, value, value2, values, value3, labels); + } + } + return new Attribute(text).read(this, value, value2, null, -1, null); + } + + public void createDebugLabel(int value, Label[] labels) { + if (labels[value] == null) { + Label label = this.createLabel(value, labels); + label.value3 = (short) (label.value3 | 1); + } + } + + public ClassReader(InputStream inputStream) throws IOException { + this(readStream(inputStream, false)); + } + + public Label createLabel(int value, Label[] labels) { + if (labels[value] == null) { + labels[value] = new Label(); + } + return labels[value]; + } + + public int[] readTypeAnnotations( + MethodVisitor methodVisitor, Context context, int value, boolean matches) { + ClassReader classReader; + char[] values = context.charBuffer; + int value2 = value; + int[] values2 = new int[this.readUnsignedShort(value2)]; + value2 += 2; + int value3; + for (int value4 = value3 = 0; value4 < values2.length; value4 = ++value3) { + int value5; + label34: + switch ((value5 = this.readInt(values2[value3] = value2)) >>> 24) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + case 19: + case 20: + case 21: + case 22: + case 24: + case 25: + case 26: + case 27: + case 28: + case 29: + case 30: + case 31: + case 32: + case 33: + case 34: + case 35: + case 36: + case 37: + case 38: + case 39: + case 40: + case 41: + case 42: + case 43: + case 44: + case 45: + case 46: + case 47: + case 48: + case 49: + case 50: + case 51: + case 52: + case 53: + case 54: + case 55: + case 56: + case 57: + case 58: + case 59: + case 60: + case 61: + case 62: + case 63: + default: + throw new IllegalArgumentException(); + case 16: + case 17: + case 18: + case 23: + case 66: + case 67: + case 68: + case 69: + case 70: + value2 += 3; + classReader = this; + break; + case 64: + case 65: + int value6 = value2; + value2 += 3; + int value7 = this.readUnsignedShort(value6 + (byte) 1); + value4 = value7; + while (true) { + int value8 = value4; + value7--; + if (value8 <= 0) { + classReader = this; + break label34; + } + int value9 = this.readUnsignedShort(value2); + int value10 = value2; + value2 += 6; + int value11 = this.readUnsignedShort(value10 + (byte) 2); + this.getLabel(value9, context.labels3); + this.getLabel(value9 + value11, context.labels3); + value4 = value7; + } + case 71: + case 72: + case 73: + case 74: + case 75: + value2 += 4; + classReader = this; + } + int value12 = classReader.readByte(value2); + if (value5 >>> 24 == 66) { + TypePath typePath = value12 == 0 ? null : new TypePath(this.classFileBuffer, value2); + int value13 = value2 + 1 + 2 * value12; + int value14 = value13; + value13 += 2; + String text2 = this.getText2(value14, values); + value2 = + this.readElementValues( + methodVisitor.createAnnotationVisitor(value5 & -256, typePath, text2, matches), + value13, + true, + values); + } else { + int value15 = value2 + 3 + 2 * value12; + value2 = this.readElementValues(null, value15, true, values); + } + } + return values2; + } + + public long readLong(int value) { + long value2 = this.readInt(value); + long value3 = this.readInt(value + 4) & 4294967295L; + return value2 << 32 | value3; + } + + public String getClassName() { + return this.getText5(this.header + 2, new char[this.maxStringLength]); + } + + public static String stringConcat$0(short value) { + return "Unsupported class file major version " + value; + } + + public String getText2(int value, char[] values) { + int value2 = this.readUnsignedShort(value); + return value != 0 && value2 != 0 ? this.getText4(value2, values) : null; + } + + public ClassReader(String text) throws IOException { + this( + readStream( + ClassLoader.getSystemResourceAsStream(stringConcat$1(text.replace('.', '/'))), true)); + } + + public String getText3(int value, char[] values) { + return this.getText6(value, values); + } + + public int readElementValue( + AnnotationVisitor annotationVisitor, int value, String text, char[] values) { + int value2 = value; + if (annotationVisitor == null) { + switch (this.classFileBuffer[value2] & 0xFF) { + case 64: + return this.readElementValues(null, value2 + 3, true, values); + case 91: + return this.readElementValues(null, value2 + 1, false, values); + case 101: + return value2 + 5; + default: + return value2 + 3; + } + } else { + int value3 = this.classFileBuffer[value2] & 255; + value2++; + switch (value3) { + case 64: + return this.readElementValues( + annotationVisitor.visitAnnotation(text, this.getText2(value2, values)), + value2 + 2, + true, + values); + case 65: + case 69: + case 71: + case 72: + case 75: + case 76: + case 77: + case 78: + case 79: + case 80: + case 81: + case 82: + case 84: + case 85: + case 86: + case 87: + case 88: + case 89: + case 92: + case 93: + case 94: + case 95: + case 96: + case 97: + case 98: + case 100: + case 102: + case 103: + case 104: + case 105: + case 106: + case 107: + case 108: + case 109: + case 110: + case 111: + case 112: + case 113: + case 114: + default: + throw new IllegalArgumentException(); + case 66: + int value4 = this.readInt(this.cpInfoOffsets[this.readUnsignedShort(value2)]); + value2 += 2; + annotationVisitor.visit(text, (byte) value4); + return value2; + case 67: + int value5 = this.readInt(this.cpInfoOffsets[this.readUnsignedShort(value2)]); + value2 += 2; + annotationVisitor.visit(text, (char) value5); + return value2; + case 68: + case 70: + case 73: + case 74: + int value6 = this.readUnsignedShort(value2); + value2 += 2; + annotationVisitor.visit(text, this.readConst(value6, values)); + return value2; + case 83: + int value7 = this.readInt(this.cpInfoOffsets[this.readUnsignedShort(value2)]); + value2 += 2; + annotationVisitor.visit(text, (short) value7); + return value2; + case 90: + annotationVisitor.visit( + text, + this.readInt(this.cpInfoOffsets[this.readUnsignedShort(value2)]) == 0 + ? Boolean.FALSE + : Boolean.TRUE); + return value2 + 2; + case 91: + int value8 = value2; + value2 += 2; + int value9 = this.readUnsignedShort(value8); + if (value9 == 0) { + return this.readElementValues( + annotationVisitor.visitArray(text), value2 - 2, false, values); + } else { + switch (this.classFileBuffer[value2] & 0xFF) { + case 66: + byte[] values2 = new byte[value9]; + int value10; + for (int value11 = value10 = 0; value11 < value9; value11 = ++value10) { + byte value12 = + (byte) this.readInt(this.cpInfoOffsets[this.readUnsignedShort(value2 + 1)]); + int value13 = value10; + value2 += 3; + values2[value13] = value12; + } + annotationVisitor.visit(text, values2); + return value2; + case 67: + char[] values3 = new char[value9]; + int value14; + for (int value15 = value14 = 0; value15 < value9; value15 = ++value14) { + char value16 = + (char) this.readInt(this.cpInfoOffsets[this.readUnsignedShort(value2 + 1)]); + int value17 = value14; + value2 += 3; + values3[value17] = value16; + } + annotationVisitor.visit(text, values3); + return value2; + case 68: + double[] values4 = new double[value9]; + int value18; + for (int value19 = value18 = 0; value19 < value9; value19 = ++value18) { + double value20 = + Double.longBitsToDouble( + this.readLong(this.cpInfoOffsets[this.readUnsignedShort(value2 + 1)])); + int value21 = value18; + value2 += 3; + values4[value21] = value20; + } + annotationVisitor.visit(text, values4); + return value2; + case 69: + case 71: + case 72: + case 75: + case 76: + case 77: + case 78: + case 79: + case 80: + case 81: + case 82: + case 84: + case 85: + case 86: + case 87: + case 88: + case 89: + default: + return this.readElementValues( + annotationVisitor.visitArray(text), value2 - 2, false, values); + case 70: + float[] values5 = new float[value9]; + int value22; + for (int value23 = value22 = 0; value23 < value9; value23 = ++value22) { + float value24 = + Float.intBitsToFloat( + this.readInt(this.cpInfoOffsets[this.readUnsignedShort(value2 + 1)])); + int value25 = value22; + value2 += 3; + values5[value25] = value24; + } + annotationVisitor.visit(text, values5); + return value2; + case 73: + int[] values6 = new int[value9]; + int value26; + for (int value27 = value26 = 0; value27 < value9; value27 = ++value26) { + int value28 = + this.readInt(this.cpInfoOffsets[this.readUnsignedShort(value2 + 1)]); + int value29 = value26; + value2 += 3; + values6[value29] = value28; + } + annotationVisitor.visit(text, values6); + return value2; + case 74: + long[] values7 = new long[value9]; + int value30; + for (int value31 = value30 = 0; value31 < value9; value31 = ++value30) { + long value32 = + this.readLong(this.cpInfoOffsets[this.readUnsignedShort(value2 + 1)]); + int value33 = value30; + value2 += 3; + values7[value33] = value32; + } + annotationVisitor.visit(text, values7); + return value2; + case 83: + short[] values8 = new short[value9]; + int value34; + for (int value35 = value34 = 0; value35 < value9; value35 = ++value34) { + short value36 = + (short) this.readInt(this.cpInfoOffsets[this.readUnsignedShort(value2 + 1)]); + int value37 = value34; + value2 += 3; + values8[value37] = value36; + } + annotationVisitor.visit(text, values8); + return value2; + case 90: + boolean[] matchess = new boolean[value9]; + int value38; + int value39 = value38 = 0; + while (value39 < value9) { + matchess[value38] = + this.readInt(this.cpInfoOffsets[this.readUnsignedShort(value2 + 1)]) != 0; + int value40 = ++value38; + value2 += 3; + value39 = value40; + } + annotationVisitor.visit(text, matchess); + return value2; + } + } + case 99: + int value41 = value2; + value2 += 2; + annotationVisitor.visit(text, Type.getType(this.getText2(value41, values))); + return value2; + case 101: + String text2 = this.getText2(value2, values); + int value42 = value2 + 2; + value2 += 4; + annotationVisitor.visitEnum(text, text2, this.getText2(value42, values)); + return value2; + case 115: + int value43 = value2; + value2 += 2; + annotationVisitor.visit(text, this.getText2(value43, values)); + return value2; + } + } + } + + public int getItem(int value) { + return this.cpInfoOffsets[value]; + } + + public final String getText4(int value, char[] values) { + String text; + if ((text = this.constantUtf8Values[value]) != null) { + return text; + } + int value2 = this.cpInfoOffsets[value]; + return this.constantUtf8Values[value] = + this.readUtf(value2 + 2, this.readUnsignedShort(value2), values); + } + + public void readParameterAnnotations( + MethodVisitor methodVisitor, Context context, int value, boolean matches) { + int value2 = value; + int value3 = this.classFileBuffer[value2] & 255; + value2++; + methodVisitor.visitAnnotableParameterCount(value3, matches); + char[] values = context.charBuffer; + int value4; + for (int value5 = value4 = 0; value5 < value3; value5 = ++value4) { + int value6 = value2; + value2 += 2; + int value7 = this.readUnsignedShort(value6); + value5 = value7; + while (true) { + int value8 = value5; + value7--; + if (value8 <= 0) { + break; + } + int value9 = value2; + value2 += 2; + String text2 = this.getText2(value9, values); + value2 = + this.readElementValues( + methodVisitor.visitParameterAnnotation(value4, text2, matches), + value2, + true, + values); + value5 = value7; + } + } + } + + public String getText2() { + return this.getText5(this.header + 4, new char[this.maxStringLength]); + } + + public void readBytecodeInstructionOffset(int value) {} + + public int readByte(int value) { + return this.classFileBuffer[value] & 0xFF; + } + + public String[] getInterfaces() { + int value; + int value2; + String[] texts = new String[value2 = this.readUnsignedShort(value = this.header + 6)]; + if (value2 > 0) { + char[] values = new char[this.maxStringLength]; + int value3; + for (int value4 = value3 = 0; value4 < value2; value4 = value3) { + int value5 = value3; + value += 2; + String text5 = this.getText5(value, values); + value3++; + texts[value5] = text5; + } + } + return texts; + } + + public ConstantDynamic readConstantDynamic(int value, char[] values) { + ConstantDynamic constantDynamic; + if ((constantDynamic = this.constantDynamicValues[value]) != null) { + return constantDynamic; + } + int value2 = this.cpInfoOffsets[value]; + int value3; + String text2 = + this.getText2(value3 = this.cpInfoOffsets[this.readUnsignedShort(value2 + 2)], values); + String text22 = this.getText2(value3 + 2, values); + int value4; + Handle handle = + (Handle) + this.readConst( + this.readUnsignedShort( + value4 = this.bootstrapMethodOffsets[this.readUnsignedShort(value2)]), + values); + Object[] results = new Object[this.readUnsignedShort(value4 + 2)]; + value4 += 4; + int value5; + for (int value6 = value5 = 0; value6 < results.length; value6 = ++value5) { + Object result = this.readConst(this.readUnsignedShort(value4), values); + int value7 = value5; + value4 += 2; + results[value7] = result; + } + return this.constantDynamicValues[value] = new ConstantDynamic(text2, text22, handle, results); + } + + public short readShort(int value) { + byte[] values = this.classFileBuffer; + return (short) ((this.classFileBuffer[value] & 255) << 8 | values[value + 1] & 0xFF); + } + + public ClassReader(byte[] values, int value, int value2) { + this(values, value, true); + } + + public String getText5(int value, char[] values) { + return this.getText6(value, values); + } + + public void accept(ClassVisitor classVisitor, Attribute[] attributes, int value) + throws ClassNotFoundException { + Context context = new Context(); + context.attributePrototypes = attributes; + context.count2 = value; + context.charBuffer = new char[this.maxStringLength]; + char[] values = context.charBuffer; + int value2 = this.header; + int value3 = this.readUnsignedShort(this.header); + String text5 = this.getText5(value2 + 2, values); + String text52 = this.getText5(value2 + 4, values); + String[] texts = new String[this.readUnsignedShort(value2 + 6)]; + value2 += 8; + int value4; + for (int value5 = value4 = 0; value5 < texts.length; value5 = ++value4) { + String text53 = this.getText5(value2, values); + int value6 = value4; + value2 += 2; + texts[value6] = text53; + } + int value7 = 0; + int value8 = 0; + String text = null; + String text2 = null; + String text3 = null; + int value9 = 0; + int value10 = 0; + int value11 = 0; + int value12 = 0; + int value13 = 0; + int value14 = 0; + String text4 = null; + String text6 = null; + int value15 = 0; + int value16 = 0; + int value17 = 0; + Attribute attribute = null; + int value18; + int value19; + for (int value20 = value19 = this.readUnsignedShort((value18 = this.calculateCount()) - 2); + value20 > 0; + value20 = value19) { + String text22 = this.getText2(value18, values); + int value21 = value18; + value18 += 6; + int value22 = this.readInt(value21 + (byte) 2); + if ("SourceFile".equals(text22)) { + text2 = this.getText2(value18, values); + value20 = value18; + } else if ("InnerClasses".equals(text22)) { + value7 = value18; + value20 = value18; + } else if ("EnclosingMethod".equals(text22)) { + value8 = value18; + value20 = value18; + } else if ("NestHost".equals(text22)) { + text6 = this.getText5(value18, values); + value20 = value18; + } else if ("NestMembers".equals(text22)) { + value15 = value18; + value20 = value18; + } else if ("PermittedSubclasses".equals(text22)) { + value16 = value18; + value20 = value18; + } else if ("Signature".equals(text22)) { + text = this.getText2(value18, values); + value20 = value18; + } else if ("RuntimeVisibleAnnotations".equals(text22)) { + value9 = value18; + value20 = value18; + } else if ("RuntimeVisibleTypeAnnotations".equals(text22)) { + value11 = value18; + value20 = value18; + } else if ("Deprecated".equals(text22)) { + value3 |= 131072; + value20 = value18; + } else if ("Synthetic".equals(text22)) { + value3 |= 4096; + value20 = value18; + } else if ("SourceDebugExtension".equals(text22)) { + if (value22 > this.classFileBuffer.length - value18) { + throw new IllegalArgumentException(); + } + text3 = this.readUtf(value18, value22, new char[value22]); + value20 = value18; + } else if ("RuntimeInvisibleAnnotations".equals(text22)) { + value10 = value18; + value20 = value18; + } else if ("RuntimeInvisibleTypeAnnotations".equals(text22)) { + value12 = value18; + value20 = value18; + } else if ("Record".equals(text22)) { + value17 = value18; + value3 |= 65536; + value20 = value18; + } else if ("Module".equals(text22)) { + value13 = value18; + value20 = value18; + } else if ("ModuleMainClass".equals(text22)) { + text4 = this.getText5(value18, values); + value20 = value18; + } else if ("ModulePackages".equals(text22)) { + value14 = value18; + value20 = value18; + } else { + if (!"BootstrapMethods".equals(text22)) { + Attribute attribute2 = + this.readAttribute(attributes, text22, value18, value22, values, -1, null); + attribute2.nextAttribute = attribute; + attribute = attribute2; + } + value20 = value18; + } + int value23 = value20; + value19--; + value18 = value23 + value22; + } + classVisitor.visit(this.readInt(this.cpInfoOffsets[1] - 7), value3, text5, text, text52, texts); + if ((value & 2) == 0 && (text2 != null || text3 != null)) { + classVisitor.visitSource(text2, text3); + } + if (value13 != 0) { + this.readModuleAttributes(classVisitor, context, value13, value14, text4); + } + if (text6 != null) { + classVisitor.visitNestHost(text6); + } + if (value8 != 0) { + String text54 = this.getText5(value8, values); + int value24; + String text7 = + (value24 = this.readUnsignedShort(value8 + 2)) == 0 + ? null + : this.getText2(this.cpInfoOffsets[value24], values); + String text8 = value24 == 0 ? null : this.getText2(this.cpInfoOffsets[value24] + 2, values); + classVisitor.visitOuterClass(text54, text7, text8); + } + if (value9 != 0) { + int value25 = this.readUnsignedShort(value9); + int value26 = value9 + 2; + int value27 = value25; + while (true) { + int value28 = value27; + value25--; + if (value28 <= 0) { + break; + } + int value29 = value26; + value26 += 2; + String text23 = this.getText2(value29, values); + value26 = + this.readElementValues( + classVisitor.visitAnnotation(text23, true), value26, true, values); + value27 = value25; + } + } + if (value10 != 0) { + int value30 = this.readUnsignedShort(value10); + int value31 = value10 + 2; + int value32 = value30; + while (true) { + int value33 = value32; + value30--; + if (value33 <= 0) { + break; + } + int value34 = value31; + value31 += 2; + String text24 = this.getText2(value34, values); + value31 = + this.readElementValues( + classVisitor.visitAnnotation(text24, false), value31, true, values); + value32 = value30; + } + } + if (value11 != 0) { + int value35 = this.readUnsignedShort(value11); + int value36 = value11 + 2; + int value37 = value35; + while (true) { + int value38 = value37; + value35--; + if (value38 <= 0) { + break; + } + int value39; + int value40 = value39 = this.readTypeAnnotationTarget(context, value36); + value39 += 2; + String text25 = this.getText2(value40, values); + value36 = + this.readElementValues( + classVisitor.visitTypeAnnotation( + context.count6, context.currentTypeAnnotationTargetPath, text25, true), + value39, + true, + values); + value37 = value35; + } + } + if (value12 != 0) { + int value41 = this.readUnsignedShort(value12); + int value42 = value12 + 2; + int value43 = value41; + while (true) { + int value44 = value43; + value41 -= 1; + if (value44 <= 0) { + break; + } + int value45; + int value46 = value45 = this.readTypeAnnotationTarget(context, value42); + value45 += 2; + String text26 = this.getText2(value46, values); + value42 = + this.readElementValues( + classVisitor.visitTypeAnnotation( + context.count6, context.currentTypeAnnotationTargetPath, text26, false), + value45, + true, + values); + value43 = value41; + } + } + Attribute attribute3 = attribute; + while (attribute3 != null) { + Attribute attribute4 = attribute.nextAttribute; + attribute.nextAttribute = null; + attribute3 = attribute4; + classVisitor.visitAttribute(attribute); + attribute = attribute4; + } + if (value15 != 0) { + int value47 = this.readUnsignedShort(value15); + int value48 = value15 + 2; + int value49 = value47; + while (true) { + int value50 = value49; + value47--; + if (value50 <= 0) { + break; + } + int value51 = value48; + value48 += 2; + classVisitor.visitNestMember(this.getText5(value51, values)); + value49 = value47; + } + } + if (value16 != 0) { + int value52 = this.readUnsignedShort(value16); + int value53 = value16 + 2; + int value54 = value52; + while (true) { + int value55 = value54; + value52--; + if (value55 <= 0) { + break; + } + int value56 = value53; + value53 += 2; + classVisitor.visitPermittedSubclass(this.getText5(value56, values)); + value54 = value52; + } + } + if (value7 != 0) { + int value57 = this.readUnsignedShort(value7); + int value58 = value7 + 2; + int value59 = value57; + while (true) { + int value60 = value59; + value57--; + if (value60 <= 0) { + break; + } + String text55 = this.getText5(value58, values); + String text56 = this.getText5(value58 + 2, values); + String text27 = this.getText2(value58 + 4, values); + int value61 = value58; + value58 += 8; + classVisitor.visitInnerClass( + text55, text56, text27, this.readUnsignedShort(value61 + (byte) 6)); + value59 = value57; + } + } + if (value17 != 0) { + int value62 = value17; + value17 += 2; + int value63 = this.readUnsignedShort(value62); + int value64 = value63; + while (true) { + int value65 = value64; + value63--; + if (value65 <= 0) { + break; + } + value17 = this.readRecordComponent(classVisitor, context, value17); + value64 = value63; + } + } + int value66 = value2; + value2 += 2; + int value67 = this.readUnsignedShort(value66); + int value68 = value67; + while (true) { + int value69 = value68; + value67--; + if (value69 <= 0) { + int value70 = value2; + value2 += 2; + int value71 = this.readUnsignedShort(value70); + int value72 = value71; + while (true) { + int value73 = value72; + value71 -= 1; + if (value73 <= 0) { + classVisitor.visitEnd(); + return; + } + value2 = this.readMethod(classVisitor, context, value2); + value72 = value71; + } + } + value2 = this.readField(classVisitor, context, value2); + value68 = value67; + } + } + + public int readTypeAnnotationTarget(Context context, int value) { + int value2 = value; + int value3; + int value4; + Context context2; + switch ((value4 = this.readInt(value)) >>> 24) { + case 0: + case 1: + case 22: + int value5 = value4; + value2 += 2; + value3 = value5 & -65536; + context2 = context; + break; + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + case 24: + case 25: + case 26: + case 27: + case 28: + case 29: + case 30: + case 31: + case 32: + case 33: + case 34: + case 35: + case 36: + case 37: + case 38: + case 39: + case 40: + case 41: + case 42: + case 43: + case 44: + case 45: + case 46: + case 47: + case 48: + case 49: + case 50: + case 51: + case 52: + case 53: + case 54: + case 55: + case 56: + case 57: + case 58: + case 59: + case 60: + case 61: + case 62: + case 63: + default: + throw new IllegalArgumentException(); + case 16: + case 17: + case 18: + case 23: + case 66: + int value6 = value4; + value2 += 3; + value3 = value6 & -256; + context2 = context; + break; + case 19: + case 20: + case 21: + int value7 = value4; + value2++; + value3 = value7 & 0xFF000000; + context2 = context; + break; + case 64: + case 65: + value3 = value4 & 0xFF000000; + int value8 = value2; + value2 += 3; + int value9 = this.readUnsignedShort(value8 + (byte) 1); + context.labels2 = new Label[value9]; + context.labels = new Label[value9]; + int value10 = 0; + context.currentLocalVariableAnnotationRangeIndices = new int[value9]; + for (int index = 0; value10 < value9; value10 = index) { + int value11 = this.readUnsignedShort(value2); + int value12 = this.readUnsignedShort(value2 + 2); + int value13 = value2; + value2 += 6; + int value14 = this.readUnsignedShort(value13 + (byte) 4); + context.labels2[index] = this.getLabel(value11, context.labels3); + context.labels[index] = this.getLabel(value11 + value12, context.labels3); + int value15 = index; + int[] values = context.currentLocalVariableAnnotationRangeIndices; + index++; + values[value15] = value14; + } + context2 = context; + break; + case 67: + case 68: + case 69: + case 70: + int value16 = value4; + value2 += 3; + value3 = value16 & 0xFF000000; + context2 = context; + break; + case 71: + case 72: + case 73: + case 74: + case 75: + int value17 = value4; + value2 += 4; + value3 = value17 & -16776961; + context2 = context; + } + context2.count6 = value3; + int value18; + context.currentTypeAnnotationTargetPath = + (value18 = this.readByte(value2)) == 0 ? null : new TypePath(this.classFileBuffer, value2); + return value2 + 1 + 2 * value18; + } + + public static int computeBufferSize(InputStream inputStream) throws IOException { + int value; + return (value = inputStream.available()) < 256 ? 4096 : Math.min(value, 1048576); + } + + public void computeImplicitFrame(Context context) { + String text3 = context.text; + Object[] results = context.values; + int value = 0; + if ((context.count7 & 8) == 0) { + if ("".equals(context.text2)) { + Integer value2 = Opcodes.INTEGER7; + int value3 = value; + value++; + results[value3] = value2; + } else { + int value4 = this.header; + int value5 = value; + value++; + results[value5] = this.getText5(value4 + 2, context.charBuffer); + } + } + int value6 = 1; + while (true) { + int value7 = value6; + char value8 = text3.charAt(value6); + value6++; + switch (value8) { + case 'B': + case 'C': + case 'I': + case 'S': + case 'Z': + Integer value9 = Opcodes.INTEGER4; + int value10 = value; + value++; + results[value10] = value9; + break; + case 'D': + Integer value11 = Opcodes.INTEGER; + int value12 = value; + value++; + results[value12] = value11; + break; + case 'E': + case 'G': + case 'H': + case 'K': + case 'M': + case 'N': + case 'O': + case 'P': + case 'Q': + case 'R': + case 'T': + case 'U': + case 'V': + case 'W': + case 'X': + case 'Y': + default: + context.count8 = value; + return; + case 'F': + Integer value13 = Opcodes.INTEGER6; + int value14 = value; + value++; + results[value14] = value13; + break; + case 'J': + Integer value15 = Opcodes.INTEGER5; + int value16 = value; + value++; + results[value16] = value15; + break; + case 'L': + String text4 = text3; + while (text4.charAt(value6) != ';') { + value6++; + text4 = text3; + } + int value17 = value; + value++; + String text5 = text3.substring(value7 + (byte) 1, value6); + value6++; + results[value17] = text5; + break; + case '[': + String text6 = text3; + while (text6.charAt(value6) == '[') { + value6++; + text6 = text3; + } + if (text3.charAt(value6) == 'L') { + value6++; + text6 = text3; + while (text6.charAt(value6) != ';') { + value6++; + text6 = text3; + } + } + int value18 = value; + value6++; + value++; + results[value18] = text3.substring(value7, value6); + } + } + } + + public ClassReader(byte[] values) { + this(values, 0, values.length); + } + + public int readInt(int value) { + byte[] values = this.classFileBuffer; + return (this.classFileBuffer[value] & 0xFF) << 24 + | (values[value + 1] & 0xFF) << 16 + | (values[value + 2] & 0xFF) << 8 + | values[value + 3] & 0xFF; + } + + public String getText6(int value, char[] values) { + return this.getText2(this.cpInfoOffsets[this.readUnsignedShort(value)], values); + } + + public void readModuleAttributes( + ClassVisitor classVisitor, Context context, int value, int value2, String text) { + char[] values = context.charBuffer; + int value3 = value; + String text2 = this.getText(value3, values); + int value4 = this.readUnsignedShort(value3 + 2); + int value5 = value3 + 4; + value3 += 6; + String text22 = this.getText2(value5, values); + ModuleVisitor moduleVisitor; + if ((moduleVisitor = classVisitor.visitModule(text2, value4, text22)) != null) { + if (text != null) { + moduleVisitor.processText(text); + } + if (value2 != 0) { + int value6 = this.readUnsignedShort(value2); + int value7 = value2 + 2; + int value8 = value6; + while (true) { + int value9 = value8; + value6--; + if (value9 <= 0) { + break; + } + int value10 = value7; + ModuleVisitor moduleVisitor2 = moduleVisitor; + value7 += 2; + moduleVisitor2.processText3(this.getText3(value10, values)); + value8 = value6; + } + } + int value11 = value3; + value3 += 2; + int value12 = this.readUnsignedShort(value11); + int value13 = value12; + while (true) { + int value14 = value13; + value12--; + if (value14 <= 0) { + int value15 = value3; + value3 += 2; + int value16 = this.readUnsignedShort(value15); + value13 = value16; + while (true) { + int value17 = value13; + value16--; + if (value17 <= 0) { + int value18 = value3; + value3 += 2; + int value19 = this.readUnsignedShort(value18); + value13 = value19; + while (true) { + int value20 = value13; + value19--; + if (value20 <= 0) { + int value21 = value3; + value3 += 2; + int value22 = this.readUnsignedShort(value21); + value13 = value22; + while (true) { + int value23 = value13; + value22--; + if (value23 <= 0) { + int value24 = value3; + value3 += 2; + int value25 = this.readUnsignedShort(value24); + value13 = value25; + while (true) { + int value26 = value13; + value25--; + if (value26 <= 0) { + moduleVisitor.visitEnd(); + return; + } + String text5 = this.getText5(value3, values); + int value27 = value3; + value3 += 4; + int value28 = this.readUnsignedShort(value27 + (byte) 2); + String[] texts = new String[value28]; + int value29; + for (int value30 = value29 = 0; value30 < value28; value30 = ++value29) { + String text52 = this.getText5(value3, values); + int value31 = value29; + value3 += 2; + texts[value31] = text52; + } + moduleVisitor.visitProvide(text5, texts); + value13 = value25; + } + } + int value32 = value3; + ModuleVisitor moduleVisitor3 = moduleVisitor; + value3 += 2; + moduleVisitor3.processText2(this.getText5(value32, values)); + value13 = value22; + } + } + String text3 = this.getText3(value3, values); + int value33 = this.readUnsignedShort(value3 + 2); + int value34 = value3; + value3 += 6; + int value35 = this.readUnsignedShort(value34 + (byte) 4); + String[] texts2 = null; + if (value35 != 0) { + texts2 = new String[value35]; + int value36; + for (int value37 = value36 = 0; value37 < value35; value37 = ++value36) { + String text4 = this.getText(value3, values); + int value38 = value36; + String[] texts3 = texts2; + value3 += 2; + texts3[value38] = text4; + } + } + moduleVisitor.processTexts2(text3, value33, texts2); + value13 = value19; + } + } + String text32 = this.getText3(value3, values); + int value39 = this.readUnsignedShort(value3 + 2); + int value40 = value3; + value3 += 6; + int value41 = this.readUnsignedShort(value40 + (byte) 4); + String[] texts4 = null; + if (value41 != 0) { + texts4 = new String[value41]; + int value42; + for (int value43 = value42 = 0; value43 < value41; value43 = ++value42) { + String text6 = this.getText(value3, values); + int value44 = value42; + String[] texts5 = texts4; + value3 += 2; + texts5[value44] = text6; + } + } + moduleVisitor.processTexts(text32, value39, texts4); + value13 = value16; + } + } + String text7 = this.getText(value3, values); + int value45 = this.readUnsignedShort(value3 + 2); + int value46 = value3 + 4; + value3 += 6; + String text23 = this.getText2(value46, values); + value13 = value12; + moduleVisitor.visitRequire(text7, value45, text23); + } + } + } + + public int readElementValues( + AnnotationVisitor annotationVisitor, int value, boolean matches, char[] values) { + int value2 = value; + int value3 = value2; + value2 += 2; + int value4 = this.readUnsignedShort(value3); + if (matches) { + int value5 = value4; + while (true) { + int value6 = value5; + value4--; + if (value6 <= 0) { + break; + } + String text2 = this.getText2(value2, values); + value2 = this.readElementValue(annotationVisitor, value2 + 2, text2, values); + value5 = value4; + } + } else { + int value7 = value4; + while (true) { + int value8 = value7; + value4--; + if (value8 <= 0) { + break; + } + value2 = this.readElementValue(annotationVisitor, value2, null, values); + value7 = value4; + } + } + if (annotationVisitor != null) { + annotationVisitor.visitEnd(); + } + return value2; + } + + public ClassReader(byte[] values, int value, boolean matches) { + super(); + this.classFileBuffer = values; + this.b = values; + if (matches && this.readShort(value + 6) > 71) { + throw new IllegalArgumentException(stringConcat$0(this.readShort(value + 6))); + } + int value2; + this.cpInfoOffsets = new int[value2 = this.readUnsignedShort(value + 8)]; + this.constantUtf8Values = new String[value2]; + int value3 = 1; + int value4 = value + 10; + int value5 = 0; + byte value6 = 0; + byte value7 = 0; + for (int value8 = value3; value8 < value2; value8 = value3) { + int value9 = value4 + 1; + int value10 = value3; + int[] values2 = this.cpInfoOffsets; + value3++; + values2[value10] = value9; + int value11; + switch (values[value4]) { + case 1: + if ((value11 = 3 + this.readUnsignedShort(value4 + 1)) > value5) { + value5 = value11; + value8 = value4; + } else { + value8 = value4; + } + break; + case 2: + case 13: + case 14: + default: + throw new IllegalArgumentException(); + case 3: + case 4: + case 9: + case 10: + case 11: + case 12: + value11 = 5; + value8 = value4; + break; + case 5: + case 6: + byte value12 = 9; + value3++; + value11 = value12; + value8 = value4; + break; + case 7: + case 8: + case 16: + case 19: + case 20: + value11 = 3; + value8 = value4; + break; + case 15: + value11 = 4; + value8 = value4; + break; + case 17: + value11 = 5; + value6 = 1; + value7 = 1; + value8 = value4; + break; + case 18: + value11 = 5; + value6 = 1; + value8 = value4; + } + value4 = value8 + value11; + } + this.maxStringLength = value5; + this.header = value4; + this.constantDynamicValues = value7 != 0 ? new ConstantDynamic[value2] : null; + this.bootstrapMethodOffsets = value6 != 0 ? this.readBootstrapMethodsAttribute(value5) : null; + } + + public static String stringConcat$1(String text) { + return "" + text + ".class"; + } + + public void readCode(MethodVisitor methodVisitor, Context context, int value) + throws ClassNotFoundException { + MethodVisitor methodVisitor2; + int value2 = value; + byte[] values3 = this.classFileBuffer; + char[] values4 = context.charBuffer; + int value3 = this.readUnsignedShort(value2); + int value4 = this.readUnsignedShort(value2 + 2); + int value5 = value2; + value2 += 8; + int value6 = this.readInt(value5 + (byte) 4); + if (value6 > this.classFileBuffer.length - value2) { + throw new IllegalArgumentException(); + } + int value7 = value2; + int value8 = value2 + value6; + Label[] labels4 = context.labels3 = new Label[value6 + 1]; + label428: + while (value2 < value8) { + int value9 = value2 - value7; + switch (values3[value2] & 0xFF) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + case 26: + case 27: + case 28: + case 29: + case 30: + case 31: + case 32: + case 33: + case 34: + case 35: + case 36: + case 37: + case 38: + case 39: + case 40: + case 41: + case 42: + case 43: + case 44: + case 45: + case 46: + case 47: + case 48: + case 49: + case 50: + case 51: + case 52: + case 53: + case 59: + case 60: + case 61: + case 62: + case 63: + case 64: + case 65: + case 66: + case 67: + case 68: + case 69: + case 70: + case 71: + case 72: + case 73: + case 74: + case 75: + case 76: + case 77: + case 78: + case 79: + case 80: + case 81: + case 82: + case 83: + case 84: + case 85: + case 86: + case 87: + case 88: + case 89: + case 90: + case 91: + case 92: + case 93: + case 94: + case 95: + case 96: + case 97: + case 98: + case 99: + case 100: + case 101: + case 102: + case 103: + case 104: + case 105: + case 106: + case 107: + case 108: + case 109: + case 110: + case 111: + case 112: + case 113: + case 114: + case 115: + case 116: + case 117: + case 118: + case 119: + case 120: + case 121: + case 122: + case 123: + case 124: + case 125: + case 126: + case 127: + case 128: + case 129: + case 130: + case 131: + case 133: + case 134: + case 135: + case 136: + case 137: + case 138: + case 139: + case 140: + case 141: + case 142: + case 143: + case 144: + case 145: + case 146: + case 147: + case 148: + case 149: + case 150: + case 151: + case 152: + case 172: + case 173: + case 174: + case 175: + case 176: + case 177: + case 190: + case 191: + case 194: + case 195: + value2++; + break; + case 16: + case 18: + case 21: + case 22: + case 23: + case 24: + case 25: + case 54: + case 55: + case 56: + case 57: + case 58: + case 169: + case 188: + value2 += 2; + break; + case 17: + case 19: + case 20: + case 132: + case 178: + case 179: + case 180: + case 181: + case 182: + case 183: + case 184: + case 187: + case 189: + case 192: + case 193: + value2 += 3; + break; + case 153: + case 154: + case 155: + case 156: + case 157: + case 158: + case 159: + case 160: + case 161: + case 162: + case 163: + case 164: + case 165: + case 166: + case 167: + case 168: + case 198: + case 199: + short value10 = this.readShort(value2 + 1); + value2 += 3; + this.getLabel(value9 + value10, labels4); + break; + case 170: + value2 += 4 - (value9 & 3); + this.getLabel(value9 + this.readInt(value2), labels4); + int value11 = this.readInt(value2 + 8) - this.readInt(value2 + 4); + value2 += 12; + int value12 = value11 + 1; + int value13 = value12; + while (true) { + int value14 = value13; + value12--; + if (value14 <= 0) { + continue label428; + } + int value15 = this.readInt(value2); + value2 += 4; + this.getLabel(value9 + value15, labels4); + value13 = value12; + } + case 171: + value2 += 4 - (value9 & 3); + this.getLabel(value9 + this.readInt(value2), labels4); + int value16 = value2; + value2 += 8; + int value17 = this.readInt(value16 + (byte) 4); + int value18 = value17; + while (true) { + int value19 = value18; + value17 -= 1; + if (value19 <= 0) { + continue label428; + } + int value20 = this.readInt(value2 + 4); + value2 += 8; + this.getLabel(value9 + value20, labels4); + value18 = value17; + } + case 185: + case 186: + value2 += 5; + break; + case 196: + switch (values3[value2 + 1] & 0xFF) { + case 21: + case 22: + case 23: + case 24: + case 25: + case 54: + case 55: + case 56: + case 57: + case 58: + case 169: + value2 += 4; + continue; + case 132: + value2 += 6; + continue; + default: + throw new IllegalArgumentException(); + } + case 197: + value2 += 4; + break; + case 200: + case 201: + case 220: + int value21 = this.readInt(value2 + 1); + value2 += 5; + this.getLabel(value9 + value21, labels4); + break; + case 202: + case 203: + case 204: + case 205: + case 206: + case 207: + case 208: + case 209: + case 210: + case 211: + case 212: + case 213: + case 214: + case 215: + case 216: + case 217: + case 218: + case 219: + int value22 = this.readUnsignedShort(value2 + 1); + value2 += 3; + this.getLabel(value9 + value22, labels4); + break; + default: + throw new IllegalArgumentException(); + } + } + int value23 = value2; + value2 += 2; + int value24 = this.readUnsignedShort(value23); + int value25 = value24; + while (true) { + int value26 = value25; + value24 -= 1; + if (value26 <= 0) { + int value27 = 0; + int value28 = 0; + byte value29 = 1; + int value30 = 0; + int value31 = 0; + int[] values5 = null; + int[] values6 = null; + Attribute attribute = null; + int value32 = value2; + value2 += 2; + int value33 = this.readUnsignedShort(value32); + value25 = value33; + while (true) { + int value34 = value25; + value33--; + if (value34 <= 0) { + int value35 = (context.count2 & 8) != 0 ? 1 : 0; + if (value27 != 0) { + context.count = -1; + context.count3 = 0; + context.count8 = 0; + context.count5 = 0; + context.values = new Object[value4]; + context.count4 = 0; + context.values2 = new Object[value3]; + if (value35 != 0) { + this.computeImplicitFrame(context); + } + int value36; + for (int value37 = value36 = value27; value37 < value28 - 2; value37 = value36) { + int value38; + if (values3[value36] == 8 + && (value38 = this.readUnsignedShort(value36 + 1)) >= 0 + && value38 < value6 + && (values3[value7 + value38] & 255) == 187) { + this.getLabel(value38, labels4); + } + value36 += 1; + } + } + if (value35 != 0 && (context.count2 & 256) != 0) { + methodVisitor.visitFrame(-1, value4, null, 0, null); + } + int value39 = 0; + int typeAnnotationBytecodeOffset = this.getTypeAnnotationBytecodeOffset(values5, 0); + int value40 = 0; + int typeAnnotationBytecodeOffset2 = this.getTypeAnnotationBytecodeOffset(values6, 0); + boolean matches = false; + int value41 = (context.count2 & 256) == 0 ? 33 : 0; + int value42 = value7; + while (value42 < value8) { + int value43 = value42 - value7; + this.readBytecodeInstructionOffset(value43); + Label label; + if ((label = labels4[value43]) != null) { + label.accept(methodVisitor, (context.count2 & 2) == 0); + } + for (int value44 = value27; + value44 != 0 && (context.count == value43 || context.count == -1); + value44 = + value27 < value28 + ? (value27 = + this.readStackMapFrame(value27, value29 != 0, value35 != 0, context)) + : (value27 = 0)) { + if (context.count != -1) { + if (value29 != 0 && value35 == 0) { + methodVisitor.visitFrame( + context.count3, + context.count5, + context.values, + context.count4, + context.values2); + } else { + methodVisitor.visitFrame( + -1, context.count8, context.values, context.count4, context.values2); + } + matches = false; + } + } + if (matches) { + if ((context.count2 & 8) != 0) { + methodVisitor.visitFrame(256, 0, null, 0, null); + } + matches = false; + } + int value45; + int[] values7; + switch (value45 = values3[value42] & 0xFF) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + case 46: + case 47: + case 48: + case 49: + case 50: + case 51: + case 52: + case 53: + case 79: + case 80: + case 81: + case 82: + case 83: + case 84: + case 85: + case 86: + case 87: + case 88: + case 89: + case 90: + case 91: + case 92: + case 93: + case 94: + case 95: + case 96: + case 97: + case 98: + case 99: + case 100: + case 101: + case 102: + case 103: + case 104: + case 105: + case 106: + case 107: + case 108: + case 109: + case 110: + case 111: + case 112: + case 113: + case 114: + case 115: + case 116: + case 117: + case 118: + case 119: + case 120: + case 121: + case 122: + case 123: + case 124: + case 125: + case 126: + case 127: + case 128: + case 129: + case 130: + case 131: + case 133: + case 134: + case 135: + case 136: + case 137: + case 138: + case 139: + case 140: + case 141: + case 142: + case 143: + case 144: + case 145: + case 146: + case 147: + case 148: + case 149: + case 150: + case 151: + case 152: + case 172: + case 173: + case 174: + case 175: + case 176: + case 177: + case 190: + case 191: + case 194: + case 195: + value42++; + methodVisitor.visitInsn(value45); + values7 = values5; + break; + case 16: + case 188: + int value46 = value42 + 1; + int value47 = value45; + value42 += 2; + methodVisitor.visitIntInsn(value47, values3[value46]); + values7 = values5; + break; + case 17: + int value48 = value42; + int value49 = value45; + value42 += 3; + methodVisitor.visitIntInsn(value49, this.readShort(value48 + (byte) 1)); + values7 = values5; + break; + case 18: + int value50 = values3[value42 + 1] & 255; + value42 += 2; + methodVisitor.visitLdcInsn(this.readConst(value50, values4)); + values7 = values5; + break; + case 19: + case 20: + int value51 = this.readUnsignedShort(value42 + 1); + value42 += 3; + methodVisitor.visitLdcInsn(this.readConst(value51, values4)); + values7 = values5; + break; + case 21: + case 22: + case 23: + case 24: + case 25: + case 54: + case 55: + case 56: + case 57: + case 58: + case 169: + byte value52 = values3[value42 + 1]; + int value53 = value45; + value42 += 2; + methodVisitor.visitVarInsn(value53, value52 & 255); + values7 = values5; + break; + case 26: + case 27: + case 28: + case 29: + case 30: + case 31: + case 32: + case 33: + case 34: + case 35: + case 36: + case 37: + case 38: + case 39: + case 40: + case 41: + case 42: + case 43: + case 44: + case 45: + value45 -= 26; + int value54 = 21 + (value45 >> 2); + int value55 = value45; + int[] values8 = values5; + value42++; + values7 = values8; + methodVisitor.visitVarInsn(value54, value55 & 3); + break; + case 59: + case 60: + case 61: + case 62: + case 63: + case 64: + case 65: + case 66: + case 67: + case 68: + case 69: + case 70: + case 71: + case 72: + case 73: + case 74: + case 75: + case 76: + case 77: + case 78: + value45 -= 59; + int value56 = 54 + (value45 >> 2); + int value57 = value45; + int[] values9 = values5; + value42++; + values7 = values9; + methodVisitor.visitVarInsn(value56, value57 & 3); + break; + case 132: + int value58 = values3[value42 + 1] & 255; + int value59 = value42 + 2; + value42 += 3; + methodVisitor.visitIincInsn(value58, values3[value59]); + values7 = values5; + break; + case 153: + case 154: + case 155: + case 156: + case 157: + case 158: + case 159: + case 160: + case 161: + case 162: + case 163: + case 164: + case 165: + case 166: + case 167: + case 168: + case 198: + case 199: + int value60 = value43 + this.readShort(value42 + 1); + int value61 = value45; + value42 += 3; + methodVisitor.visitJumpInsn(value61, labels4[value60]); + values7 = values5; + break; + case 170: + value42 += 4 - (value43 & 3); + Label label2 = labels4[value43 + this.readInt(value42)]; + int value62 = this.readInt(value42 + 4); + int value63 = value42; + value42 += 12; + int value64 = this.readInt(value63 + (byte) 8); + Label[] labels5 = new Label[value64 - value62 + 1]; + int value65; + for (int value66 = value65 = 0; value66 < labels5.length; value66 = ++value65) { + Label label3 = labels4[value43 + this.readInt(value42)]; + int value67 = value65; + value42 += 4; + labels5[value67] = label3; + } + methodVisitor.visitTableSwitchInsn(value62, value64, label2, labels5); + values7 = values5; + break; + case 171: + value42 += 4 - (value43 & 3); + Label label4 = labels4[value43 + this.readInt(value42)]; + int value68 = value42; + value42 += 8; + int value69 = this.readInt(value68 + (byte) 4); + int[] values10 = new int[value69]; + Label[] labels6 = new Label[value69]; + int value70; + for (int value71 = value70 = 0; value71 < value69; value71 = value70) { + values10[value70] = this.readInt(value42); + Label label5 = labels4[value43 + this.readInt(value42 + 4)]; + int value72 = value70; + value42 += 8; + labels6[value72] = label5; + value70 += 1; + } + methodVisitor.visitLookupSwitchInsn(label4, values10, labels6); + values7 = values5; + break; + case 178: + case 179: + case 180: + case 181: + case 182: + case 183: + case 184: + case 185: + int value73 = this.cpInfoOffsets[this.readUnsignedShort(value42 + 1)]; + int value74 = this.cpInfoOffsets[this.readUnsignedShort(value73 + 2)]; + String text5 = this.getText5(value73, values4); + String text2 = this.getText2(value74, values4); + String text22 = this.getText2(value74 + 2, values4); + if (value45 < 182) { + value25 = value45; + methodVisitor.visitFieldInsn(value45, text5, text2, text22); + } else { + boolean matches2 = values3[value73 - 1] == 11; + value25 = value45; + methodVisitor.visitMethodInsn(value45, text5, text2, text22, matches2); + } + if (value25 == 185) { + int[] values11 = values5; + value42 += 5; + values7 = values11; + } else { + value42 += 3; + values7 = values5; + } + break; + case 186: + int value75 = this.cpInfoOffsets[this.readUnsignedShort(value42 + 1)]; + int value76; + String text23 = + this.getText2( + value76 = this.cpInfoOffsets[this.readUnsignedShort(value75 + 2)], + values4); + String text24 = this.getText2(value76 + 2, values4); + int value77; + Handle handle = + (Handle) + this.readConst( + this.readUnsignedShort( + value77 = + this.bootstrapMethodOffsets[this.readUnsignedShort(value75)]), + values4); + Object[] results = new Object[this.readUnsignedShort(value77 + 2)]; + value77 += 4; + int value78; + for (int value79 = value78 = 0; value79 < results.length; value79 = value78) { + Object result = this.readConst(this.readUnsignedShort(value77), values4); + int value80 = value78; + value77 += 2; + results[value80] = result; + value78 += 1; + } + value42 += 5; + methodVisitor.visitInvokeDynamicInsn(text23, text24, handle, results); + values7 = values5; + break; + case 187: + case 189: + case 192: + case 193: + int value81 = value42 + 1; + int value82 = value45; + value42 += 3; + methodVisitor.visitTypeInsn(value82, this.getText5(value81, values4)); + values7 = values5; + break; + case 196: + int value83; + if ((value83 = values3[value42 + 1] & 255) == 132) { + int value84 = this.readUnsignedShort(value42 + 2); + int value85 = value42; + int[] values12 = values5; + value42 += 6; + values7 = values12; + methodVisitor.visitIincInsn(value84, this.readShort(value85 + (byte) 4)); + } else { + int value86 = value42; + int value87 = value83; + value42 += 4; + methodVisitor.visitVarInsn(value87, this.readUnsignedShort(value86 + (byte) 2)); + values7 = values5; + } + break; + case 197: + String text52 = this.getText5(value42 + 1, values4); + byte value88 = values3[value42 + 3]; + value42 += 4; + methodVisitor.visitMultiANewArrayInsn(text52, value88 & 255); + values7 = values5; + break; + case 200: + case 201: + int value89 = value45 - value41; + int value90 = value43 + this.readInt(value42 + 1); + value42 += 5; + methodVisitor.visitJumpInsn(value89, labels4[value90]); + values7 = values5; + break; + case 202: + case 203: + case 204: + case 205: + case 206: + case 207: + case 208: + case 209: + case 210: + case 211: + case 212: + case 213: + case 214: + case 215: + case 216: + case 217: + case 218: + case 219: + int value91 = value45 < 218 ? value45 - 49 : value45 - 20; + Label label6 = labels4[value43 + this.readUnsignedShort(value42 + 1)]; + if (value91 != 167 && value91 != 168) { + int value92 = value91 < 167 ? (value91 + 1 ^ 1) - 1 : value91 ^ 1; + Label label7 = this.getLabel(value43 + 3, labels4); + methodVisitor.visitJumpInsn(value92, label7); + methodVisitor.visitJumpInsn(200, label6); + matches = true; + } else { + methodVisitor.visitJumpInsn(value91 + 33, label6); + } + value42 += 3; + values7 = values5; + break; + case 220: + Label label8 = labels4[value43 + this.readInt(value42 + 1)]; + value42 += 5; + methodVisitor.visitJumpInsn((short) 200, label8); + matches = true; + values7 = values5; + break; + default: + throw new AssertionError(); + } + while (values7 != null + && value39 < values5.length + && typeAnnotationBytecodeOffset <= value43) { + if (typeAnnotationBytecodeOffset == value43) { + int value93; + int value94 = value93 = this.readTypeAnnotationTarget(context, values5[value39]); + value93 += 2; + String text25 = this.getText2(value94, values4); + this.readElementValues( + methodVisitor.createAnnotationVisitor3( + context.count6, context.currentTypeAnnotationTargetPath, text25, true), + value93, + true, + values4); + } + typeAnnotationBytecodeOffset = + this.getTypeAnnotationBytecodeOffset(values5, ++value39); + values7 = values5; + } + for (int[] values13 = values6; + values13 != null + && value40 < values6.length + && typeAnnotationBytecodeOffset2 <= value43; + values13 = values6) { + if (typeAnnotationBytecodeOffset2 == value43) { + int value95; + int value96 = value95 = this.readTypeAnnotationTarget(context, values6[value40]); + value95 += 2; + String text26 = this.getText2(value96, values4); + this.readElementValues( + methodVisitor.createAnnotationVisitor3( + context.count6, context.currentTypeAnnotationTargetPath, text26, false), + value95, + true, + values4); + } + value40 += 1; + typeAnnotationBytecodeOffset2 = + this.getTypeAnnotationBytecodeOffset(values6, value40); + } + } + if (labels4[value6] != null) { + methodVisitor.visitLabel(labels4[value6]); + } + if (value30 != 0 && (context.count2 & 2) == 0) { + int[] values14 = null; + if (value31 != 0) { + values14 = new int[this.readUnsignedShort(value31) * 3]; + int value97 = value31 + 2; + int value98; + for (int value99 = value98 = values14.length; value99 > 0; value99 = value98) { + int value100 = value98 - 1; + int value101 = value97 + 6; + int[] values15 = values14; + int[] values16 = values14; + int[] values17 = values14; + int value102 = value100 - 1; + values15[value100] = value101; + int value103 = this.readUnsignedShort(value97 + 8); + value98 = value102 - 1; + values16[value102] = value103; + int value104 = this.readUnsignedShort(value97); + int value105 = value98; + value97 += 10; + values17[value105] = value104; + } + } + int value106 = this.readUnsignedShort(value30); + int value107 = value30 + 2; + value25 = value106; + while (true) { + int value108 = value25; + value106 -= 1; + if (value108 <= 0) { + break; + } + int value109; + int value110; + String text; + int value111; + String text3; + String text4; + label285: + { + value111 = this.readUnsignedShort(value107); + value110 = this.readUnsignedShort(value107 + 2); + text4 = this.getText2(value107 + 4, values4); + text3 = this.getText2(value107 + 6, values4); + int value112 = value107; + value107 += 10; + value109 = this.readUnsignedShort(value112 + (byte) 8); + text = null; + int value113; + if (values14 != null) { + for (int value114 = value113 = 0; + value114 < values14.length; + value114 = value113) { + if (values14[value113] == value111 && values14[value113 + 1] == value109) { + text = this.getText2(values14[value113 + 2], values4); + methodVisitor2 = methodVisitor; + break label285; + } + value113 += 3; + } + } + methodVisitor2 = methodVisitor; + } + methodVisitor2.visitLocalVariable( + text4, text3, text, labels4[value111], labels4[value111 + value110], value109); + value25 = value106; + } + } + if (values5 != null) { + int[] values18 = values5; + int value115 = values5.length; + int value116; + for (int value117 = value116 = 0; value117 < value115; value117 = ++value116) { + int value118; + int value119; + if ((value118 = this.readByte(value119 = values18[value116])) == 64 + || value118 == 65) { + int value120; + int value121 = value120 = this.readTypeAnnotationTarget(context, value119); + value120 += 2; + String text27 = this.getText2(value121, values4); + this.readElementValues( + methodVisitor.visitLocalVariableAnnotation( + context.count6, + context.currentTypeAnnotationTargetPath, + context.labels2, + context.labels, + context.currentLocalVariableAnnotationRangeIndices, + text27, + true), + value120, + true, + values4); + } + } + } + if (values6 != null) { + int[] values19 = values6; + int value122 = values6.length; + int value123; + for (int value124 = value123 = 0; value124 < value122; value124 = value123) { + int value125; + int value126; + if ((value126 = this.readByte(value125 = values19[value123])) == 64 + || value126 == 65) { + int value127; + int value128 = value127 = this.readTypeAnnotationTarget(context, value125); + value127 += 2; + String text28 = this.getText2(value128, values4); + this.readElementValues( + methodVisitor.visitLocalVariableAnnotation( + context.count6, + context.currentTypeAnnotationTargetPath, + context.labels2, + context.labels, + context.currentLocalVariableAnnotationRangeIndices, + text28, + false), + value127, + true, + values4); + } + value123 += 1; + } + } + Attribute attribute2 = attribute; + while (attribute2 != null) { + Attribute attribute3 = attribute.nextAttribute; + attribute.nextAttribute = null; + attribute2 = attribute3; + methodVisitor.visitAttribute(attribute); + attribute = attribute3; + } + methodVisitor.visitMaxs(value3, value4); + return; + } + int value129; + label404: + { + String text29 = this.getText2(value2, values4); + int value130 = value2; + value2 += 6; + value129 = this.readInt(value130 + (byte) 2); + if ("LocalVariableTable".equals(text29)) { + if ((context.count2 & 2) == 0) { + value30 = value2; + int value131 = value2; + int value132 = value131; + value131 += 2; + int value133 = this.readUnsignedShort(value132); + value25 = value133; + while (true) { + int value134 = value25; + value133 -= 1; + if (value134 <= 0) { + break; + } + int value135; + this.createDebugLabel(value135 = this.readUnsignedShort(value131), labels4); + int value136 = this.readUnsignedShort(value131 + 2); + int value137 = value135; + value131 += 10; + this.createDebugLabel(value137 + value136, labels4); + value25 = value133; + } + } + } else { + if ("LocalVariableTypeTable".equals(text29)) { + value31 = value2; + value25 = value2; + break label404; + } + if ("LineNumberTable".equals(text29)) { + if ((context.count2 & 2) == 0) { + int value138 = value2; + int value139 = value138; + value138 += 2; + int value140 = this.readUnsignedShort(value139); + value25 = value140; + while (true) { + int value141 = value25; + value140 -= 1; + if (value141 <= 0) { + break; + } + int value142 = this.readUnsignedShort(value138); + int value143 = value138; + value138 += 4; + int value144 = this.readUnsignedShort(value143 + (byte) 2); + this.createDebugLabel(value142, labels4); + labels4[value142].addLineNumber(value144); + value25 = value140; + } + } + } else { + if ("RuntimeVisibleTypeAnnotations".equals(text29)) { + values5 = this.readTypeAnnotations(methodVisitor, context, value2, true); + value25 = value2; + break label404; + } + if ("RuntimeInvisibleTypeAnnotations".equals(text29)) { + values6 = this.readTypeAnnotations(methodVisitor, context, value2, false); + value25 = value2; + break label404; + } + if ("StackMapTable".equals(text29)) { + if ((context.count2 & 4) == 0) { + value27 = value2 + 2; + value28 = value2 + value129; + value25 = value2; + break label404; + } + } else if ("StackMap".equals(text29)) { + if ((context.count2 & 4) == 0) { + value27 = value2 + 2; + value28 = value2 + value129; + value29 = 0; + value25 = value2; + break label404; + } + } else { + Attribute attribute4 = + this.readAttribute( + context.attributePrototypes, + text29, + value2, + value129, + values4, + value, + labels4); + attribute4.nextAttribute = attribute; + attribute = attribute4; + } + } + } + value25 = value2; + } + value2 = value25 + value129; + value25 = value33; + } + } + Label label9 = this.getLabel(this.readUnsignedShort(value2), labels4); + Label label10 = this.getLabel(this.readUnsignedShort(value2 + 2), labels4); + Label label11 = this.getLabel(this.readUnsignedShort(value2 + 4), labels4); + int value145 = this.cpInfoOffsets[this.readUnsignedShort(value2 + 6)]; + value2 += 8; + String text210 = this.getText2(value145, values4); + value25 = value24; + methodVisitor.visitTryCatchBlock(label9, label10, label11, text210); + } + } + + public int getMaxStringLength() { + return this.maxStringLength; + } + + public int getItemCount() { + return this.cpInfoOffsets.length; + } + + public int getTypeAnnotationBytecodeOffset(int[] values, int value) { + return values != null && value < values.length && this.readByte(values[value]) >= 67 + ? this.readUnsignedShort(values[value] + 1) + : -1; + } +} diff --git a/src/main/java/com/allatori/lib/asm/ClassTooLargeException.java b/src/main/java/com/allatori/lib/asm/ClassTooLargeException.java new file mode 100644 index 0000000..e1529e9 --- /dev/null +++ b/src/main/java/com/allatori/lib/asm/ClassTooLargeException.java @@ -0,0 +1,28 @@ +package com.allatori.lib.asm; + +public final class ClassTooLargeException extends IndexOutOfBoundsException { + + public final int constantPoolCount; + + public final String className; + + public static final long serialVersionUID = 160715609518896765L; + + public int getConstantPoolCount() { + return this.constantPoolCount; + } + + public String getClassName() { + return this.className; + } + + public ClassTooLargeException(String className, int constantPoolCount) { + super(stringConcat$0(className)); + this.className = className; + this.constantPoolCount = constantPoolCount; + } + + public static String stringConcat$0(String text) { + return "Class too large: " + text; + } +} diff --git a/src/main/java/com/allatori/lib/asm/ClassVisitor.java b/src/main/java/com/allatori/lib/asm/ClassVisitor.java new file mode 100644 index 0000000..7b85569 --- /dev/null +++ b/src/main/java/com/allatori/lib/asm/ClassVisitor.java @@ -0,0 +1,144 @@ +package com.allatori.lib.asm; + +public abstract class ClassVisitor { + + public final int api; + + public ClassVisitor cv; + + public AnnotationVisitor visitAnnotation(String text, boolean matches) { + return this.cv != null ? this.cv.visitAnnotation(text, matches) : null; + } + + public void visitSource(String text, String text2) { + if (this.cv != null) { + this.cv.visitSource(text, text2); + } + } + + public void visitPermittedSubclass(String text) { + if (this.api < 589824) { + throw new UnsupportedOperationException("PermittedSubclasses requires ASM9"); + } + if (this.cv != null) { + this.cv.visitPermittedSubclass(text); + } + } + + public ClassVisitor(int value) { + this(value, null); + } + + public void visitOuterClass(String text, String text2, String text3) { + if (this.cv != null) { + this.cv.visitOuterClass(text, text2, text3); + } + } + + public void visit( + int value, int value2, String text, String text2, String text3, String[] texts) { + if (this.api < 524288 && (value2 & 65536) != 0) { + throw new UnsupportedOperationException("Records requires ASM8"); + } + if (this.cv != null) { + this.cv.visit(value, value2, text, text2, text3, texts); + } + } + + public ClassVisitor getDelegate() { + return this.cv; + } + + public FieldVisitor visitField( + int value, String text, String text2, String text3, Object result) { + return this.cv != null ? this.cv.visitField(value, text, text2, text3, result) : null; + } + + public ModuleVisitor visitModule(String text, int value, String text2) { + if (this.api < 393216) { + throw new UnsupportedOperationException("Module requires ASM6"); + } else { + return this.cv != null ? this.cv.visitModule(text, value, text2) : null; + } + } + + public AnnotationVisitor visitTypeAnnotation( + int value, TypePath typePath, String text, boolean matches) { + if (this.api < 327680) { + throw new UnsupportedOperationException("TypeAnnotation requires ASM5"); + } else { + return this.cv != null ? this.cv.visitTypeAnnotation(value, typePath, text, matches) : null; + } + } + + public void visitInnerClass(String text, String text2, String text3, int value) { + if (this.cv != null) { + this.cv.visitInnerClass(text, text2, text3, value); + } + } + + public void visitEnd() { + if (this.cv != null) { + this.cv.visitEnd(); + } + } + + public void visitNestMember(String text) { + if (this.api < 458752) { + throw new UnsupportedOperationException("NestMember requires ASM7"); + } + if (this.cv != null) { + this.cv.visitNestMember(text); + } + } + + public MethodVisitor visitMethod( + int value, String text, String text2, String text3, String[] texts) { + return this.cv != null ? this.cv.visitMethod(value, text, text2, text3, texts) : null; + } + + public static String stringConcat$0(int value) { + return "Unsupported api " + value; + } + + public void visitNestHost(String text) { + if (this.api < 458752) { + throw new UnsupportedOperationException("NestHost requires ASM7"); + } + if (this.cv != null) { + this.cv.visitNestHost(text); + } + } + + public ClassVisitor(int api, ClassVisitor classVisitor) { + super(); + if (api != 589824 + && api != 524288 + && api != 458752 + && api != 393216 + && api != 327680 + && api != 262144 + && api != 17432576) { + throw new IllegalArgumentException(stringConcat$0(api)); + } + if (api == 17432576) { + Constants.checkAsmExperimental(this); + } + this.api = api; + this.cv = classVisitor; + } + + public void visitAttribute(Attribute attribute) { + if (this.cv != null) { + this.cv.visitAttribute(attribute); + } + } + + public RecordComponentVisitor visitRecordComponent(String text, String text2, String text3) { + if (this.api < 524288) { + throw new UnsupportedOperationException("Record requires ASM8"); + } else { + return this.cv != null ? this.cv.visitRecordComponent(text, text2, text3) : null; + } + } +} diff --git a/src/main/java/com/allatori/lib/asm/ClassWriter.java b/src/main/java/com/allatori/lib/asm/ClassWriter.java new file mode 100644 index 0000000..0752ad7 --- /dev/null +++ b/src/main/java/com/allatori/lib/asm/ClassWriter.java @@ -0,0 +1,668 @@ +package com.allatori.lib.asm; + +public class ClassWriter extends ClassVisitor { + + public int count; + + public int count2; + + public int count3; + + public AnnotationWriter annotationWriter; + + public int count4; + + public AnnotationWriter annotationWriter2; + + public ByteVector byteVector; + + public RecordComponentWriter recordComponentWriter; + + public int count5; + + public AnnotationWriter annotationWriter3; + + public MethodWriter methodWriter; + + public int count6; + + public int count7; + + public int[] interfaces; + + public FieldWriter fieldWriter; + + public final int flags; + + public static final int COMPUTE_MAXS = 1; + + public AnnotationWriter annotationWriter4; + + public ModuleWriter moduleWriter; + + public int count8; + + public int count9; + + public int count10; + + public final SymbolTable symbolTable; + + public int count11; + + public int count12; + + public ByteVector byteVector2; + + public Attribute firstAttribute; + + public RecordComponentWriter recordComponentWriter2; + + public int count13; + + public MethodWriter methodWriter2; + + public static final int COMPUTE_FRAMES = 2; + + public int count14; + + public ByteVector byteVector3; + + public ByteVector byteVector4; + + public FieldWriter fieldWriter2; + + public String getCommonSuperClass(String text, String text2) throws ClassNotFoundException { + ClassLoader classLoader = this.getClassLoader(); + Class classValue; + try { + classValue = Class.forName(text.replace('/', '.'), false, classLoader); + } catch (ClassNotFoundException classNotFoundException) { + throw new TypeNotPresentException(text, classNotFoundException); + } + Class classValue2 = Class.forName(text2.replace('/', '.'), false, classLoader); + if (classValue.isAssignableFrom(classValue2)) { + return text; + } + if (classValue2.isAssignableFrom(classValue)) { + return text2; + } + if (!classValue.isInterface() && !classValue2.isInterface()) { + while (!(classValue = classValue.getSuperclass()).isAssignableFrom(classValue2)) {} + return classValue.getName().replace('.', '/'); + } else { + return "java/lang/Object"; + } + } + + public int calculateCount(String text) { + return this.symbolTable.getSymbol(text).index; + } + + @Override + public final void visitNestMember(String text) { + if (this.byteVector4 == null) { + this.byteVector4 = new ByteVector(); + } + this.count7++; + this.byteVector4.putShort(this.symbolTable.getSymbol3(text).index); + } + + @Override + public final void visitSource(String text, String text2) { + if (text != null) { + this.count4 = this.symbolTable.addConstantUtf8(text); + } + if (text2 != null) { + this.byteVector2 = new ByteVector().encodeUtf8(text2, 0, Integer.MAX_VALUE); + } + } + + @Override + public final void visitNestHost(String text) { + this.count14 = this.symbolTable.getSymbol3(text).index; + } + + @Override + public final void visitEnd() {} + + @Override + public final void visitAttribute(Attribute attribute) { + attribute.nextAttribute = this.firstAttribute; + this.firstAttribute = attribute; + } + + @Override + public final void visitPermittedSubclass(String text) { + if (this.byteVector3 == null) { + this.byteVector3 = new ByteVector(); + } + this.count9++; + this.byteVector3.putShort(this.symbolTable.getSymbol3(text).index); + } + + public Attribute[] getAttributePrototypes() { + Attribute$Set attribute$Set; + (attribute$Set = new Attribute$Set()).addAttributes(this.firstAttribute); + FieldWriter fieldWriter2; + for (FieldWriter fieldWriter3 = fieldWriter2 = this.fieldWriter; + fieldWriter3 != null; + fieldWriter3 = fieldWriter2 = (FieldWriter) fieldWriter2.fv) { + fieldWriter2.collectAttributePrototypes(attribute$Set); + } + MethodWriter methodWriter2; + for (MethodWriter methodWriter3 = methodWriter2 = this.methodWriter; + methodWriter3 != null; + methodWriter3 = methodWriter2 = (MethodWriter) methodWriter2.mv) { + methodWriter2.collectAttributePrototypes(attribute$Set); + } + RecordComponentWriter recordComponentWriter; + for (RecordComponentWriter recordComponentWriter3 = + recordComponentWriter = this.recordComponentWriter2; + recordComponentWriter3 != null; + recordComponentWriter3 = + recordComponentWriter = (RecordComponentWriter) recordComponentWriter.delegate) { + recordComponentWriter.collectAttributePrototypes(attribute$Set); + } + return attribute$Set.toArray(); + } + + public int newConst(Object result) { + return this.symbolTable.addConstant(result).index; + } + + public int calculateCount2(String text) { + return this.symbolTable.getSymbol3(text).index; + } + + public int calculateCount3(String text) { + return this.symbolTable.getSymbol2(text).index; + } + + public ClassLoader getClassLoader() { + return this.getClass().getClassLoader(); + } + + public int newHandle(int value, String text, String text2, String text3, boolean matches) { + return this.symbolTable.addConstantMethodHandle(value, text, text2, text3, matches).index; + } + + @Deprecated + public int newHandle(int value, String text, String text2, String text3) { + return this.newHandle(value, text, text2, text3, value == 9); + } + + public int newConstantDynamic(String text, String text2, Handle handle, Object... result) { + return this.symbolTable.addConstantDynamic(text, text2, handle, (Object[]) result).index; + } + + @Override + public final void visit( + int count10, int count5, String text, String text2, String text3, String[] texts) { + this.count10 = count10; + this.count5 = count5; + this.count2 = this.symbolTable.setMajorVersionAndClassName(count10 & 65535, text); + if (text2 != null) { + this.count3 = this.symbolTable.addConstantUtf8(text2); + } + this.count12 = text3 == null ? 0 : this.symbolTable.getSymbol3(text3).index; + if (texts != null && texts.length > 0) { + this.count6 = texts.length; + int value3 = 0; + this.interfaces = new int[this.count6]; + for (int index2 = 0; value3 < this.count6; value3 = index2) { + int[] values = this.interfaces; + int value4 = this.symbolTable.getSymbol3(texts[index2]).index; + int value5 = index2; + index2++; + values[value5] = value4; + } + } + if (this.count8 == 1 && (count10 & 65535) >= 51) { + this.count8 = 2; + } + } + + public int newField(String text, String text2, String text3) { + return this.symbolTable.addConstantFieldref(text, text2, text3).index; + } + + public int newInvokeDynamic(String text, String text2, Handle handle, Object... result) { + return this.symbolTable.addConstantInvokeDynamic(text, text2, handle, (Object[]) result).index; + } + + public boolean hasFlags(int value) { + return (this.flags & value) == value; + } + + @Override + public final RecordComponentVisitor visitRecordComponent( + String text, String text2, String text3) { + RecordComponentWriter recordComponentWriter3 = + new RecordComponentWriter(this.symbolTable, text, text2, text3); + ClassWriter classWriter; + if (this.recordComponentWriter2 == null) { + classWriter = this; + this.recordComponentWriter2 = recordComponentWriter3; + } else { + classWriter = this; + this.recordComponentWriter.delegate = recordComponentWriter3; + } + return classWriter.recordComponentWriter = recordComponentWriter3; + } + + public byte[] replaceAsmInstructions(byte[] values, boolean matches) + throws ClassNotFoundException { + Attribute[] attributePrototypes = this.getAttributePrototypes(); + this.fieldWriter = null; + this.fieldWriter2 = null; + this.methodWriter = null; + this.methodWriter2 = null; + this.annotationWriter = null; + this.annotationWriter4 = null; + this.annotationWriter3 = null; + this.annotationWriter2 = null; + this.moduleWriter = null; + this.count14 = 0; + this.count7 = 0; + this.byteVector4 = null; + this.count9 = 0; + this.byteVector3 = null; + this.recordComponentWriter2 = null; + this.recordComponentWriter = null; + this.firstAttribute = null; + this.count8 = matches ? 3 : 0; + new ClassReader(values, 0, false).accept(this, attributePrototypes, (matches ? 8 : 0) | 256); + return this.toByteArray(); + } + + public int newNameType(String text, String text2) { + return this.symbolTable.addConstantNameAndType(text, text2); + } + + @Override + public final ModuleVisitor visitModule(String text, int value, String text2) { + return this.moduleWriter = + new ModuleWriter( + this.symbolTable, + this.symbolTable.getSymbol4(text).index, + value, + text2 == null ? 0 : this.symbolTable.addConstantUtf8(text2)); + } + + @Override + public final AnnotationVisitor visitAnnotation(String text, boolean matches) { + return matches + ? (this.annotationWriter = + AnnotationWriter.create(this.symbolTable, text, this.annotationWriter)) + : (this.annotationWriter4 = + AnnotationWriter.create(this.symbolTable, text, this.annotationWriter4)); + } + + public ClassWriter(int value) { + this(null, value); + } + + public byte[] toByteArray() throws ClassNotFoundException { + int value = 24 + 2 * this.count6; + int value2 = 0; + FieldWriter fieldWriter2; + for (FieldWriter fieldWriter3 = fieldWriter2 = this.fieldWriter; + fieldWriter3 != null; + fieldWriter3 = fieldWriter2 = (FieldWriter) fieldWriter2.fv) { + int value3 = fieldWriter2.computeFieldInfoSize(); + int value4 = value; + value2++; + value = value4 + value3; + } + int value5 = 0; + MethodWriter methodWriter2; + for (MethodWriter methodWriter3 = methodWriter2 = this.methodWriter; + methodWriter3 != null; + methodWriter3 = methodWriter2 = (MethodWriter) methodWriter2.mv) { + int value6 = methodWriter2.computeMethodInfoSize(); + int value7 = value; + value5++; + value = value7 + value6; + } + int value8 = 0; + if (this.byteVector != null) { + int value9 = value; + value8++; + value = value9 + (byte) 8 + this.byteVector.length; + this.symbolTable.addConstantUtf8("InnerClasses"); + } + if (this.count11 != 0) { + value += 10; + SymbolTable symbolTable2 = this.symbolTable; + value8++; + symbolTable2.addConstantUtf8("EnclosingMethod"); + } + if ((this.count5 & 4096) != 0 && (this.count10 & 65535) < 49) { + value += 6; + SymbolTable symbolTable3 = this.symbolTable; + value8++; + symbolTable3.addConstantUtf8("Synthetic"); + } + if (this.count3 != 0) { + value += 8; + SymbolTable symbolTable4 = this.symbolTable; + value8++; + symbolTable4.addConstantUtf8("Signature"); + } + if (this.count4 != 0) { + value += 8; + SymbolTable symbolTable5 = this.symbolTable; + value8++; + symbolTable5.addConstantUtf8("SourceFile"); + } + if (this.byteVector2 != null) { + int value10 = value; + value8++; + value = value10 + (byte) 6 + this.byteVector2.length; + this.symbolTable.addConstantUtf8("SourceDebugExtension"); + } + if ((this.count5 & 131072) != 0) { + value += 6; + SymbolTable symbolTable6 = this.symbolTable; + value8++; + symbolTable6.addConstantUtf8("Deprecated"); + } + if (this.annotationWriter != null) { + AnnotationWriter annotationWriter5 = this.annotationWriter; + int value11 = value; + value8++; + value = value11 + annotationWriter5.computeAnnotationsSize("RuntimeVisibleAnnotations"); + } + if (this.annotationWriter4 != null) { + AnnotationWriter annotationWriter6 = this.annotationWriter4; + int value12 = value; + value8++; + value = value12 + annotationWriter6.computeAnnotationsSize("RuntimeInvisibleAnnotations"); + } + if (this.annotationWriter3 != null) { + AnnotationWriter annotationWriter7 = this.annotationWriter3; + int value13 = value; + value8++; + value = value13 + annotationWriter7.computeAnnotationsSize("RuntimeVisibleTypeAnnotations"); + } + if (this.annotationWriter2 != null) { + AnnotationWriter annotationWriter8 = this.annotationWriter2; + int value14 = value; + value8++; + value = value14 + annotationWriter8.computeAnnotationsSize("RuntimeInvisibleTypeAnnotations"); + } + if (this.symbolTable.computeBootstrapMethodsSize() > 0) { + SymbolTable symbolTable7 = this.symbolTable; + int value15 = value; + value8++; + value = value15 + symbolTable7.computeBootstrapMethodsSize(); + } + if (this.moduleWriter != null) { + value8 += this.moduleWriter.getAttributeCount(); + value += this.moduleWriter.computeAttributesSize(); + } + if (this.count14 != 0) { + value += 8; + SymbolTable symbolTable8 = this.symbolTable; + value8++; + symbolTable8.addConstantUtf8("NestHost"); + } + if (this.byteVector4 != null) { + int value16 = value; + value8++; + value = value16 + (byte) 8 + this.byteVector4.length; + this.symbolTable.addConstantUtf8("NestMembers"); + } + if (this.byteVector3 != null) { + int value17 = value; + value8++; + value = value17 + (byte) 8 + this.byteVector3.length; + this.symbolTable.addConstantUtf8("PermittedSubclasses"); + } + int value18 = 0; + int value19 = 0; + if ((this.count5 & 65536) != 0 || this.recordComponentWriter2 != null) { + RecordComponentWriter recordComponentWriter; + for (RecordComponentWriter recordComponentWriter3 = + recordComponentWriter = this.recordComponentWriter2; + recordComponentWriter3 != null; + recordComponentWriter3 = + recordComponentWriter = (RecordComponentWriter) recordComponentWriter.delegate) { + int value20 = recordComponentWriter.computeRecordComponentInfoSize(); + int value21 = value19; + value18++; + value19 = value21 + value20; + } + value8++; + value += 8 + value19; + this.symbolTable.addConstantUtf8("Record"); + } + if (this.firstAttribute != null) { + value8 += this.firstAttribute.getAttributeCount(); + value += this.firstAttribute.computeAttributesSize(this.symbolTable); + } + int value22 = value + this.symbolTable.calculateCount(); + int value23; + if ((value23 = this.symbolTable.getConstantPoolCount()) > 65535) { + throw new ClassTooLargeException(this.symbolTable.getClassName(), value23); + } + ByteVector byteVector5; + (byteVector5 = new ByteVector(value22)).putInt(-889275714).putInt(this.count10); + this.symbolTable.processByteVector(byteVector5); + int value24 = (this.count10 & 65535) < 49 ? 4096 : 0; + byteVector5.putShort(this.count5 & ~value24).putShort(this.count2).putShort(this.count12); + byteVector5.putShort(this.count6); + int value25 = 0; + for (int value26 = value25; value26 < this.count6; value26 = value25) { + int value27 = value25; + int[] values = this.interfaces; + ByteVector byteVector6 = byteVector5; + value25++; + byteVector6.putShort(values[value27]); + } + byteVector5.putShort(value2); + FieldWriter fieldWriter4 = this.fieldWriter; + for (FieldWriter fieldWriter5 = fieldWriter4; + fieldWriter5 != null; + fieldWriter5 = fieldWriter4 = (FieldWriter) fieldWriter4.fv) { + fieldWriter4.putFieldInfo(byteVector5); + } + byteVector5.putShort(value5); + boolean matches = false; + boolean matches2 = false; + MethodWriter methodWriter4 = this.methodWriter; + for (MethodWriter methodWriter5 = methodWriter4; + methodWriter5 != null; + methodWriter5 = methodWriter4 = (MethodWriter) methodWriter4.mv) { + matches |= methodWriter4.isCount7(); + matches2 |= methodWriter4.isEnabled2(); + methodWriter4.putMethodInfo(byteVector5); + } + byteVector5.putShort(value8); + if (this.byteVector != null) { + byteVector5 + .putShort(this.symbolTable.addConstantUtf8("InnerClasses")) + .putInt(this.byteVector.length + 2) + .putShort(this.count) + .putByteArray(this.byteVector.data, 0, this.byteVector.length); + } + if (this.count11 != 0) { + byteVector5 + .putShort(this.symbolTable.addConstantUtf8("EnclosingMethod")) + .putInt(4) + .putShort(this.count11) + .putShort(this.count13); + } + if ((this.count5 & 4096) != 0 && (this.count10 & 65535) < 49) { + byteVector5.putShort(this.symbolTable.addConstantUtf8("Synthetic")).putInt(0); + } + if (this.count3 != 0) { + byteVector5 + .putShort(this.symbolTable.addConstantUtf8("Signature")) + .putInt(2) + .putShort(this.count3); + } + if (this.count4 != 0) { + byteVector5 + .putShort(this.symbolTable.addConstantUtf8("SourceFile")) + .putInt(2) + .putShort(this.count4); + } + if (this.byteVector2 != null) { + int value28 = this.byteVector2.length; + byteVector5 + .putShort(this.symbolTable.addConstantUtf8("SourceDebugExtension")) + .putInt(value28) + .putByteArray(this.byteVector2.data, 0, value28); + } + if ((this.count5 & 131072) != 0) { + byteVector5.putShort(this.symbolTable.addConstantUtf8("Deprecated")).putInt(0); + } + AnnotationWriter.putAnnotations( + this.symbolTable, + this.annotationWriter, + this.annotationWriter4, + this.annotationWriter3, + this.annotationWriter2, + byteVector5); + this.symbolTable.processByteVector2(byteVector5); + if (this.moduleWriter != null) { + this.moduleWriter.putAttributes(byteVector5); + } + if (this.count14 != 0) { + byteVector5 + .putShort(this.symbolTable.addConstantUtf8("NestHost")) + .putInt(2) + .putShort(this.count14); + } + if (this.byteVector4 != null) { + byteVector5 + .putShort(this.symbolTable.addConstantUtf8("NestMembers")) + .putInt(this.byteVector4.length + 2) + .putShort(this.count7) + .putByteArray(this.byteVector4.data, 0, this.byteVector4.length); + } + if (this.byteVector3 != null) { + byteVector5 + .putShort(this.symbolTable.addConstantUtf8("PermittedSubclasses")) + .putInt(this.byteVector3.length + 2) + .putShort(this.count9) + .putByteArray(this.byteVector3.data, 0, this.byteVector3.length); + } + if ((this.count5 & 65536) != 0 || this.recordComponentWriter2 != null) { + byteVector5 + .putShort(this.symbolTable.addConstantUtf8("Record")) + .putInt(value19 + 2) + .putShort(value18); + RecordComponentWriter recordComponentWriter4 = this.recordComponentWriter2; + for (RecordComponentWriter recordComponentWriter5 = recordComponentWriter4; + recordComponentWriter5 != null; + recordComponentWriter5 = + recordComponentWriter4 = (RecordComponentWriter) recordComponentWriter4.delegate) { + recordComponentWriter4.putRecordComponentInfo(byteVector5); + } + } + if (this.firstAttribute != null) { + this.firstAttribute.putAttributes(this.symbolTable, byteVector5); + } + return matches2 ? this.replaceAsmInstructions(byteVector5.data, matches) : byteVector5.data; + } + + @Override + public final AnnotationVisitor visitTypeAnnotation( + int value, TypePath typePath, String text, boolean matches) { + return matches + ? (this.annotationWriter3 = + AnnotationWriter.create( + this.symbolTable, value, typePath, text, this.annotationWriter3)) + : (this.annotationWriter2 = + AnnotationWriter.create( + this.symbolTable, value, typePath, text, this.annotationWriter2)); + } + + @Override + public final void visitOuterClass(String text, String text2, String text3) { + this.count11 = this.symbolTable.getSymbol3(text).index; + if (text2 != null && text3 != null) { + this.count13 = this.symbolTable.addConstantNameAndType(text2, text3); + } + } + + @Override + public final void visitInnerClass(String text, String text2, String text3, int value) { + if (this.byteVector == null) { + this.byteVector = new ByteVector(); + } + Symbol symbol; + if ((symbol = this.symbolTable.getSymbol3(text)).count == 0) { + this.count++; + this.byteVector.putShort(symbol.index); + this.byteVector.putShort(text2 == null ? 0 : this.symbolTable.getSymbol3(text2).index); + this.byteVector.putShort(text3 == null ? 0 : this.symbolTable.addConstantUtf8(text3)); + this.byteVector.putShort(value); + symbol.count = this.count; + } + } + + public ClassWriter(ClassReader classReader, int flags) { + super(589824); + this.flags = flags; + this.symbolTable = + classReader == null ? new SymbolTable(this) : new SymbolTable(this, classReader); + this.setFlags(flags); + } + + @Override + public final MethodVisitor visitMethod( + int value, String text, String text2, String text3, String[] texts) { + MethodWriter methodWriter3 = + new MethodWriter(this.symbolTable, value, text, text2, text3, texts, this.count8); + ClassWriter classWriter; + if (this.methodWriter == null) { + classWriter = this; + this.methodWriter = methodWriter3; + } else { + classWriter = this; + this.methodWriter2.mv = methodWriter3; + } + return classWriter.methodWriter2 = methodWriter3; + } + + public int calculateCount4(String text) { + return this.symbolTable.getSymbol4(text).index; + } + + public int newUTF8(String text) { + return this.symbolTable.addConstantUtf8(text); + } + + public int newMethod(String text, String text2, String text3, boolean matches) { + return this.symbolTable.addConstantMethodref(text, text2, text3, matches).index; + } + + public final void setFlags(int value) { + if ((value & 2) != 0) { + this.count8 = 4; + } else if ((value & 1) != 0) { + this.count8 = 1; + } else { + this.count8 = 0; + } + } + + @Override + public final FieldVisitor visitField( + int value, String text, String text2, String text3, Object result) { + FieldWriter fieldWriter3 = new FieldWriter(this.symbolTable, value, text, text2, text3, result); + ClassWriter classWriter; + if (this.fieldWriter == null) { + classWriter = this; + this.fieldWriter = fieldWriter3; + } else { + classWriter = this; + this.fieldWriter2.fv = fieldWriter3; + } + return classWriter.fieldWriter2 = fieldWriter3; + } +} diff --git a/src/main/java/com/allatori/lib/asm/ConstantDynamic.java b/src/main/java/com/allatori/lib/asm/ConstantDynamic.java new file mode 100644 index 0000000..c6768be --- /dev/null +++ b/src/main/java/com/allatori/lib/asm/ConstantDynamic.java @@ -0,0 +1,78 @@ +package com.allatori.lib.asm; + +import java.util.Arrays; + +public final class ConstantDynamic { + + public final String name; + + public final String descriptor; + + public final Handle bootstrapMethod; + + public final Object[] bootstrapMethodArguments; + + public static String stringConcat$0(String text, String text2, String text3, String text4) { + return "" + text + " : " + text2 + " " + text3 + " " + text4; + } + + public ConstantDynamic(String name, String descriptor, Handle handle, Object... result) { + super(); + this.name = name; + this.descriptor = descriptor; + this.bootstrapMethod = handle; + this.bootstrapMethodArguments = (Object[]) result; + } + + public int getBootstrapMethodArgumentCount() { + return this.bootstrapMethodArguments.length; + } + + public Handle getBootstrapMethod() { + return this.bootstrapMethod; + } + + @Override + public boolean equals(Object result) { + if (result == this) { + return true; + } + if (!(result instanceof ConstantDynamic)) { + return false; + } + ConstantDynamic constantDynamic = (ConstantDynamic) result; + return this.name.equals(constantDynamic.name) + && this.descriptor.equals(constantDynamic.descriptor) + && this.bootstrapMethod.equals(constantDynamic.bootstrapMethod) + && Arrays.equals(this.bootstrapMethodArguments, constantDynamic.bootstrapMethodArguments); + } + + @Override + public int hashCode() { + return this.name.hashCode() + ^ Integer.rotateLeft(this.descriptor.hashCode(), 8) + ^ Integer.rotateLeft(this.bootstrapMethod.hashCode(), 16) + ^ Integer.rotateLeft(Arrays.hashCode(this.bootstrapMethodArguments), 24); + } + + public Object[] getBootstrapMethodArgumentsUnsafe() { + return this.bootstrapMethodArguments; + } + + public String getName() { + return this.name; + } + + public String getDescriptor() { + return this.descriptor; + } + + public Object getBootstrapMethodArgument(int value) { + return this.bootstrapMethodArguments[value]; + } + + public int getSize() { + char value; + return (value = this.descriptor.charAt(0)) != 74 && value != 68 ? 1 : 2; + } +} diff --git a/src/main/java/com/allatori/lib/asm/Constants.java b/src/main/java/com/allatori/lib/asm/Constants.java new file mode 100644 index 0000000..a9c58d7 --- /dev/null +++ b/src/main/java/com/allatori/lib/asm/Constants.java @@ -0,0 +1,265 @@ +package com.allatori.lib.asm; + +import java.io.DataInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.regex.Pattern; + +public final class Constants { + + public static final String TEXT8 = "ConstantValue"; + + public static final String TEXT26 = "Code"; + + public static final String TEXT17 = "StackMapTable"; + + public static final String TEXT10 = "Exceptions"; + + public static final String TEXT5 = "InnerClasses"; + + public static final String TEXT25 = "EnclosingMethod"; + + public static final String TEXT29 = "Synthetic"; + + public static final String TEXT3 = "Signature"; + + public static final String TEXT15 = "SourceFile"; + + public static final String TEXT14 = "SourceDebugExtension"; + + public static final String TEXT13 = "LineNumberTable"; + + public static final String TEXT27 = "LocalVariableTable"; + + public static final String TEXT30 = "LocalVariableTypeTable"; + + public static final String TEXT2 = "Deprecated"; + + public static final String TEXT20 = "RuntimeVisibleAnnotations"; + + public static final String TEXT7 = "RuntimeInvisibleAnnotations"; + + public static final String TEXT = "RuntimeVisibleParameterAnnotations"; + + public static final String TEXT23 = "RuntimeInvisibleParameterAnnotations"; + + public static final String TEXT21 = "RuntimeVisibleTypeAnnotations"; + + public static final String TEXT9 = "RuntimeInvisibleTypeAnnotations"; + + public static final String TEXT22 = "AnnotationDefault"; + + public static final String TEXT11 = "BootstrapMethods"; + + public static final String TEXT4 = "MethodParameters"; + + public static final String TEXT19 = "Module"; + + public static final String TEXT16 = "ModulePackages"; + + public static final String TEXT18 = "ModuleMainClass"; + + public static final String TEXT24 = "NestHost"; + + public static final String TEXT12 = "NestMembers"; + + public static final String TEXT28 = "PermittedSubclasses"; + + public static final String TEXT6 = "Record"; + + public static final int FSTORE_3 = 70; + + public static final int ILOAD_1 = 27; + + public static final int LSTORE_3 = 66; + + public static final int COUNT = 20; + + public static final int LSTORE_2 = 65; + + public static final int ASM_GOTO_W = 220; + + public static final int ASM_IFNE = 203; + + public static final int ASM_JSR = 217; + + public static final int ILOAD_3 = 29; + + public static final int FLOAD_3 = 37; + + public static final int ALOAD_0 = 42; + + public static final int ASM_IF_ICMPGT = 212; + + public static final int FLOAD_0 = 34; + + public static final int LSTORE_0 = 63; + + public static final int DLOAD_3 = 41; + + public static final int COUNT2 = 33; + + public static final int ASM_IF_ACMPNE = 215; + + public static final int ASM_IFGE = 205; + + public static final int DSTORE_0 = 71; + + public static final int F_INSERT = 256; + + public static final int ACC_CONSTRUCTOR = 262144; + + public static final int ASTORE_2 = 77; + + public static final int ASM_IF_ICMPLT = 210; + + public static final int ASM_IF_ICMPLE = 213; + + public static final int COUNT3 = 20; + + public static final int ASM_IF_ACMPEQ = 214; + + public static final int GOTO_W = 200; + + public static final int LLOAD_0 = 30; + + public static final int ASM_IFNONNULL = 219; + + public static final int FLOAD_2 = 36; + + public static final int ILOAD_0 = 26; + + public static final int DSTORE_3 = 74; + + public static final int ASM_IF_ICMPEQ = 208; + + public static final int ASM_IFEQ = 202; + + public static final int JSR_W = 201; + + public static final int DLOAD_2 = 40; + + public static final int DLOAD_1 = 39; + + public static final int ASTORE_1 = 76; + + public static final int LLOAD_1 = 31; + + public static final int FLOAD_1 = 35; + + public static final int ASM_IFGT = 206; + + public static final int LSTORE_1 = 64; + + public static final int ASM_IF_ICMPNE = 209; + + public static final int ISTORE_3 = 62; + + public static final int DSTORE_1 = 72; + + public static final int ASTORE_3 = 78; + + public static final int ILOAD_2 = 28; + + public static final int FSTORE_0 = 67; + + public static final int ISTORE_1 = 60; + + public static final int ASM_IF_ICMPGE = 211; + + public static final int DLOAD_0 = 38; + + public static final int FSTORE_2 = 69; + + public static final int ASM_OPCODE_DELTA = 49; + + public static final int COUNT4 = 33; + + public static final int ASM_IFLT = 204; + + public static final int ASM_IFNULL = 218; + + public static final int DSTORE_2 = 73; + + public static final int FSTORE_1 = 68; + + public static final int LDC_W = 19; + + public static final int ASTORE_0 = 75; + + public static final int ISTORE_0 = 59; + + public static final int WIDE = 196; + + public static final int LLOAD_2 = 32; + + public static final int ALOAD_1 = 43; + + public static final int ALOAD_2 = 44; + + public static final int ASM_GOTO = 216; + + public static final int ASM_IFLE = 207; + + public static final int ISTORE_2 = 61; + + public static final int ALOAD_3 = 45; + + public static String createText(String text) { + return "" + text + ".class"; + } + + public static boolean isWhitelisted(String text) { + if (!text.startsWith("org/objectweb/asm/")) { + return false; + } + String text2 = "(Annotation|Class|Field|Method|Module|RecordComponent|Signature)"; + return text.contains("Test$") + || Pattern.matches(createText3(text2), text) + || Pattern.matches(createText2(text2), text); + } + + public static void checkAsmExperimental(Object result) { + Class classValue; + String text; + if (!isWhitelisted(text = (classValue = result.getClass()).getName().replace('.', '/'))) { + checkIsPreview(classValue.getClassLoader().getResourceAsStream(createText(text))); + } + } + + public static String createText2(String text) { + return "org/objectweb/asm/util/Check" + text + "Adapter(\\$.*)?"; + } + + public static void checkIsPreview(InputStream inputStream) { + if (inputStream == null) { + throw new IllegalStateException("Bytecode not available, can't check class version"); + } + int value; + try { + DataInputStream dataInputStream = new DataInputStream(inputStream); + try { + dataInputStream.readInt(); + value = dataInputStream.readUnsignedShort(); + } catch (Throwable throwable) { + try { + dataInputStream.close(); + } catch (Throwable throwable2) { + throw throwable; + } + throw throwable; + } + dataInputStream.close(); + } catch (IOException oException) { + throw new IllegalStateException("I/O error, can't check class version", oException); + } + if (value != 65535) { + throw new IllegalStateException( + "ASM10_EXPERIMENTAL can only be used by classes compiled with --enable-preview"); + } + } + + public static String createText3(String text) { + return "org/objectweb/asm/util/Trace" + text + "Visitor(\\$.*)?"; + } +} diff --git a/src/main/java/com/allatori/lib/asm/Context.java b/src/main/java/com/allatori/lib/asm/Context.java new file mode 100644 index 0000000..ce5da5f --- /dev/null +++ b/src/main/java/com/allatori/lib/asm/Context.java @@ -0,0 +1,42 @@ +package com.allatori.lib.asm; + +public final class Context { + + public Object[] values; + + public Attribute[] attributePrototypes; + + public TypePath currentTypeAnnotationTargetPath; + + public int count; + + public Label[] labels; + + public Label[] labels2; + + public int count2; + + public Label[] labels3; + + public int count3; + + public int[] currentLocalVariableAnnotationRangeIndices; + + public int count4; + + public char[] charBuffer; + + public String text; + + public String text2; + + public int count5; + + public int count6; + + public int count7; + + public int count8; + + public Object[] values2; +} diff --git a/src/main/java/com/allatori/lib/asm/CurrentFrame.java b/src/main/java/com/allatori/lib/asm/CurrentFrame.java new file mode 100644 index 0000000..3fe205d --- /dev/null +++ b/src/main/java/com/allatori/lib/asm/CurrentFrame.java @@ -0,0 +1,17 @@ +package com.allatori.lib.asm; + +public final class CurrentFrame extends Frame { + + public CurrentFrame(Label label) { + super(label); + } + + @Override + public void execute(int value, int value2, Symbol symbol, SymbolTable symbolTable) + throws ClassNotFoundException { + super.execute(value, value2, symbol, symbolTable); + Frame frame = new Frame(null); + this.merge(symbolTable, frame, 0); + this.copyFrom(frame); + } +} diff --git a/src/main/java/com/allatori/lib/asm/Edge.java b/src/main/java/com/allatori/lib/asm/Edge.java new file mode 100644 index 0000000..5b67582 --- /dev/null +++ b/src/main/java/com/allatori/lib/asm/Edge.java @@ -0,0 +1,21 @@ +package com.allatori.lib.asm; + +public final class Edge { + + public final Label successor; + + public final int info; + + public static final int JUMP = 0; + + public static final int EXCEPTION = Integer.MAX_VALUE; + + public Edge nextEdge; + + public Edge(int info, Label label, Edge edge) { + super(); + this.info = info; + this.successor = label; + this.nextEdge = edge; + } +} diff --git a/src/main/java/com/allatori/lib/asm/FieldVisitor.java b/src/main/java/com/allatori/lib/asm/FieldVisitor.java new file mode 100644 index 0000000..0e86153 --- /dev/null +++ b/src/main/java/com/allatori/lib/asm/FieldVisitor.java @@ -0,0 +1,63 @@ +package com.allatori.lib.asm; + +public abstract class FieldVisitor { + + public FieldVisitor fv; + + public final int api; + + public AnnotationVisitor visitAnnotation(String text, boolean matches) { + return this.fv != null ? this.fv.visitAnnotation(text, matches) : null; + } + + public void visitEnd() { + if (this.fv != null) { + this.fv.visitEnd(); + } + } + + public static String stringConcat$0(int value) { + return "Unsupported api " + value; + } + + public AnnotationVisitor visitTypeAnnotation( + int value, TypePath typePath, String text, boolean matches) { + if (this.api < 327680) { + throw new UnsupportedOperationException("This feature requires ASM5"); + } else { + return this.fv != null ? this.fv.visitTypeAnnotation(value, typePath, text, matches) : null; + } + } + + public void visitAttribute(Attribute attribute) { + if (this.fv != null) { + this.fv.visitAttribute(attribute); + } + } + + public FieldVisitor getDelegate() { + return this.fv; + } + + public FieldVisitor(int value) { + this(value, null); + } + + public FieldVisitor(int api, FieldVisitor fieldVisitor) { + super(); + if (api != 589824 + && api != 524288 + && api != 458752 + && api != 393216 + && api != 327680 + && api != 262144 + && api != 17432576) { + throw new IllegalArgumentException(stringConcat$0(api)); + } + if (api == 17432576) { + Constants.checkAsmExperimental(this); + } + this.api = api; + this.fv = fieldVisitor; + } +} diff --git a/src/main/java/com/allatori/lib/asm/FieldWriter.java b/src/main/java/com/allatori/lib/asm/FieldWriter.java new file mode 100644 index 0000000..bd48b11 --- /dev/null +++ b/src/main/java/com/allatori/lib/asm/FieldWriter.java @@ -0,0 +1,156 @@ +package com.allatori.lib.asm; + +public final class FieldWriter extends FieldVisitor { + + public final int accessFlags; + + public AnnotationWriter annotationWriter; + + public AnnotationWriter annotationWriter2; + + public AnnotationWriter annotationWriter3; + + public final int descriptorIndex; + + public final int nameIndex; + + public int signatureIndex; + + public int constantValueIndex; + + public Attribute firstAttribute; + + public final SymbolTable symbolTable; + + public AnnotationWriter annotationWriter4; + + @Override + public AnnotationVisitor visitAnnotation(String text, boolean matches) { + return matches + ? (this.annotationWriter4 = + AnnotationWriter.create(this.symbolTable, text, this.annotationWriter4)) + : (this.annotationWriter2 = + AnnotationWriter.create(this.symbolTable, text, this.annotationWriter2)); + } + + @Override + public void visitAttribute(Attribute attribute) { + attribute.nextAttribute = this.firstAttribute; + this.firstAttribute = attribute; + } + + public FieldWriter( + SymbolTable symbolTable2, + int accessFlags, + String text, + String text2, + String text3, + Object result) { + super(589824); + this.symbolTable = symbolTable2; + this.accessFlags = accessFlags; + this.nameIndex = symbolTable2.addConstantUtf8(text); + this.descriptorIndex = symbolTable2.addConstantUtf8(text2); + if (text3 != null) { + this.signatureIndex = symbolTable2.addConstantUtf8(text3); + } + if (result != null) { + this.constantValueIndex = symbolTable2.addConstant(result).index; + } + } + + @Override + public AnnotationVisitor visitTypeAnnotation( + int value, TypePath typePath, String text, boolean matches) { + return matches + ? (this.annotationWriter = + AnnotationWriter.create(this.symbolTable, value, typePath, text, this.annotationWriter)) + : (this.annotationWriter3 = + AnnotationWriter.create( + this.symbolTable, value, typePath, text, this.annotationWriter3)); + } + + public int computeFieldInfoSize() { + int value = 8; + if (this.constantValueIndex != 0) { + SymbolTable symbolTable2 = this.symbolTable; + value += 8; + symbolTable2.addConstantUtf8("ConstantValue"); + } + int value2 = + value + + Attribute.computeAttributesSize( + this.symbolTable, this.accessFlags, this.signatureIndex) + + AnnotationWriter.computeAnnotationsSize( + this.annotationWriter4, + this.annotationWriter2, + this.annotationWriter, + this.annotationWriter3); + if (this.firstAttribute != null) { + value2 += this.firstAttribute.computeAttributesSize(this.symbolTable); + } + return value2; + } + + @Override + public void visitEnd() {} + + public final void collectAttributePrototypes(Attribute$Set attribute$Set) { + attribute$Set.addAttributes(this.firstAttribute); + } + + public void putFieldInfo(ByteVector byteVector) { + int value = this.symbolTable.getCount() < 49 ? 1 : 0; + int value2 = value != 0 ? 4096 : 0; + byteVector + .putShort(this.accessFlags & ~value2) + .putShort(this.nameIndex) + .putShort(this.descriptorIndex); + int value3 = 0; + if (this.constantValueIndex != 0) { + value3++; + } + if ((this.accessFlags & 4096) != 0 && value != 0) { + value3++; + } + if (this.signatureIndex != 0) { + value3++; + } + if ((this.accessFlags & 131072) != 0) { + value3++; + } + if (this.annotationWriter4 != null) { + value3++; + } + if (this.annotationWriter2 != null) { + value3++; + } + if (this.annotationWriter != null) { + value3++; + } + if (this.annotationWriter3 != null) { + value3++; + } + if (this.firstAttribute != null) { + value3 += this.firstAttribute.getAttributeCount(); + } + byteVector.putShort(value3); + if (this.constantValueIndex != 0) { + byteVector + .putShort(this.symbolTable.addConstantUtf8("ConstantValue")) + .putInt(2) + .putShort(this.constantValueIndex); + } + Attribute.putAttributes(this.symbolTable, this.accessFlags, this.signatureIndex, byteVector); + AnnotationWriter.putAnnotations( + this.symbolTable, + this.annotationWriter4, + this.annotationWriter2, + this.annotationWriter, + this.annotationWriter3, + byteVector); + if (this.firstAttribute != null) { + this.firstAttribute.putAttributes(this.symbolTable, byteVector); + } + } +} diff --git a/src/main/java/com/allatori/lib/asm/Frame.java b/src/main/java/com/allatori/lib/asm/Frame.java new file mode 100644 index 0000000..3a3cc6a --- /dev/null +++ b/src/main/java/com/allatori/lib/asm/Frame.java @@ -0,0 +1,1298 @@ +package com.allatori.lib.asm; + +public class Frame { + + public static final int NULL = 4194309; + + public static final int STACK_KIND = 25165824; + + public static final int COUNT = 20; + + public static final int UNINITIALIZED_KIND = 12582912; + + public static final int ITEM_ASM_CHAR = 11; + + public static final int DOUBLE = 4194307; + + public static final int ITEM_DOUBLE = 3; + + public int[] counts; + + public static final int COUNT2 = 20; + + public static final int ARRAY_OF = 67108864; + + public static final int SHORT = 4194316; + + public static final int BOOLEAN = 4194313; + + public static final int INTEGER = 4194305; + + public static final int ITEM_INTEGER = 1; + + public static final int UNINITIALIZED_THIS = 4194310; + + public static final int SAME_FRAME_EXTENDED = 251; + + public static final int RESERVED = 128; + + public static final int COUNT3 = 6; + + public static final int KIND_MASK = 62914560; + + public int[] counts2; + + public static final int FULL_FRAME = 255; + + public static final int KIND_SHIFT = 22; + + public int initializationCount; + + public static final int ITEM_NULL = 5; + + public static final int APPEND_FRAME = 252; + + public static final int LONG = 4194308; + + public static final int COUNT4 = 0; + + public static final int FLOAT = 4194306; + + public static final int COUNT5 = 4; + + public static final int COUNT6 = -67108864; + + public static final int REFERENCE_KIND = 8388608; + + public static final int ITEM_ASM_SHORT = 12; + + public static final int COUNT7 = 4; + + public static final int COUNT8 = 4194304; + + public static final int ITEM_ASM_BOOLEAN = 9; + + public static final int ITEM_UNINITIALIZED = 8; + + public static final int COUNT9 = 0; + + public static final int VALUE_MASK = 1048575; + + public int[] counts3; + + public static final int ITEM_OBJECT = 7; + + public static final int FORWARD_UNINITIALIZED_KIND = 16777216; + + public static final int DIM_SHIFT = 26; + + public short value; + + public static final int TOP_IF_LONG_OR_DOUBLE_FLAG = 1048576; + + public static final int COUNT10 = 2; + + public static final int COUNT11 = 6; + + public static final int SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED = 247; + + public static final int CHOP_FRAME = 248; + + public static final int BYTE = 4194314; + + public static final int LOCAL_KIND = 20971520; + + public static final int COUNT12 = 2; + + public int[] counts4; + + public static final int CHAR = 4194315; + + public Label owner; + + public short value2; + + public static final int COUNT13 = 4194304; + + public static final int SAME_LOCALS_1_STACK_ITEM_FRAME = 64; + + public int[] counts5; + + public static final int ITEM_ASM_BYTE = 10; + + public static final int COUNT14 = -67108864; + + public static String createText(String text) { + return "Invalid descriptor fragment: " + text; + } + + public void processCount(int value3) { + if (this.value >= value3) { + this.value = (short) (this.value - value3); + } else { + this.value2 = (short) (this.value2 - (value3 - this.value)); + this.value = 0; + } + } + + public Frame(Label label) { + super(); + this.owner = label; + } + + public static String createText2(String text) { + return "Invalid descriptor: " + text; + } + + public void execute(int value2, int value3, Symbol symbol, SymbolTable symbolTable) + throws ClassNotFoundException { + switch (value2) { + case 0: + case 116: + case 117: + case 118: + case 119: + case 145: + case 146: + case 147: + case 167: + case 177: + return; + case 1: + this.processCount3(4194309); + return; + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 16: + case 17: + case 21: + this.processCount3(4194305); + return; + case 9: + case 10: + case 22: + this.processCount3(4194308); + this.processCount3(4194304); + return; + case 11: + case 12: + case 13: + case 23: + this.processCount3(4194306); + return; + case 14: + case 15: + case 24: + this.processCount3(4194307); + this.processCount3(4194304); + return; + case 18: + switch (symbol.tag) { + case 3: + this.processCount3(4194305); + return; + case 4: + this.processCount3(4194306); + return; + case 5: + this.processCount3(4194308); + this.processCount3(4194304); + return; + case 6: + this.processCount3(4194307); + this.processCount3(4194304); + return; + case 7: + this.processCount3(8388608 | symbolTable.addType("java/lang/Class")); + return; + case 8: + this.processCount3(8388608 | symbolTable.addType("java/lang/String")); + return; + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + default: + throw new AssertionError(); + case 15: + this.processCount3(8388608 | symbolTable.addType("java/lang/invoke/MethodHandle")); + return; + case 16: + this.processCount3(8388608 | symbolTable.addType("java/lang/invoke/MethodType")); + return; + case 17: + this.push(symbolTable, symbol.value); + return; + } + case 19: + case 20: + case 26: + case 27: + case 28: + case 29: + case 30: + case 31: + case 32: + case 33: + case 34: + case 35: + case 36: + case 37: + case 38: + case 39: + case 40: + case 41: + case 42: + case 43: + case 44: + case 45: + case 59: + case 60: + case 61: + case 62: + case 63: + case 64: + case 65: + case 66: + case 67: + case 68: + case 69: + case 70: + case 71: + case 72: + case 73: + case 74: + case 75: + case 76: + case 77: + case 78: + case 196: + default: + throw new IllegalArgumentException(); + case 25: + this.processCount3(this.getLocal(value3)); + return; + case 46: + case 51: + case 52: + case 53: + case 96: + case 100: + case 104: + case 108: + case 112: + case 120: + case 122: + case 124: + case 126: + case 128: + case 130: + case 136: + case 142: + case 149: + case 150: + this.processCount(2); + this.processCount3(4194305); + return; + case 47: + case 143: + this.processCount(2); + this.processCount3(4194308); + this.processCount3(4194304); + return; + case 48: + case 98: + case 102: + case 106: + case 110: + case 114: + case 137: + case 144: + this.processCount(2); + this.processCount3(4194306); + return; + case 49: + case 138: + this.processCount(2); + this.processCount3(4194307); + this.processCount3(4194304); + return; + case 50: + this.processCount(1); + int value4; + this.processCount3( + (value4 = this.calculateCount()) == 4194309 ? value4 : -67108864 + value4); + return; + case 54: + case 56: + case 58: + int value5 = this.calculateCount(); + this.setLocal(value3, value5); + if (value3 > 0) { + int value6; + if ((value6 = this.getLocal(value3 - 1)) == 4194308 || value6 == 4194307) { + this.setLocal(value3 - 1, 4194304); + return; + } + if ((value6 & 62914560) == 20971520 || (value6 & 62914560) == 25165824) { + this.setLocal(value3 - 1, value6 | 1048576); + return; + } + } + break; + case 55: + case 57: + this.processCount(1); + int value7 = this.calculateCount(); + this.setLocal(value3, value7); + this.setLocal(value3 + 1, 4194304); + if (value3 > 0) { + int value8; + if ((value8 = this.getLocal(value3 - 1)) == 4194308 || value8 == 4194307) { + this.setLocal(value3 - 1, 4194304); + return; + } + if ((value8 & 62914560) == 20971520 || (value8 & 62914560) == 25165824) { + this.setLocal(value3 - 1, value8 | 1048576); + return; + } + } + break; + case 79: + case 81: + case 83: + case 84: + case 85: + case 86: + this.processCount(3); + return; + case 80: + case 82: + this.processCount(4); + return; + case 87: + case 153: + case 154: + case 155: + case 156: + case 157: + case 158: + case 170: + case 171: + case 172: + case 174: + case 176: + case 191: + case 194: + case 195: + case 198: + case 199: + this.processCount(1); + return; + case 88: + case 159: + case 160: + case 161: + case 162: + case 163: + case 164: + case 165: + case 166: + case 173: + case 175: + this.processCount(2); + return; + case 89: + int value9; + this.processCount3(value9 = this.calculateCount()); + this.processCount3(value9); + return; + case 90: + int value10 = this.calculateCount(); + int value11 = this.calculateCount(); + this.processCount3(value10); + this.processCount3(value11); + this.processCount3(value10); + return; + case 91: + int value12 = this.calculateCount(); + int value13 = this.calculateCount(); + int value14 = this.calculateCount(); + this.processCount3(value12); + this.processCount3(value14); + this.processCount3(value13); + this.processCount3(value12); + return; + case 92: + int value15 = this.calculateCount(); + int value16; + this.processCount3(value16 = this.calculateCount()); + this.processCount3(value15); + this.processCount3(value16); + this.processCount3(value15); + return; + case 93: + int value17 = this.calculateCount(); + int value18 = this.calculateCount(); + int value19 = this.calculateCount(); + this.processCount3(value18); + this.processCount3(value17); + this.processCount3(value19); + this.processCount3(value18); + this.processCount3(value17); + return; + case 94: + int value20 = this.calculateCount(); + int value21 = this.calculateCount(); + int value22 = this.calculateCount(); + int value23 = this.calculateCount(); + this.processCount3(value21); + this.processCount3(value20); + this.processCount3(value23); + this.processCount3(value22); + this.processCount3(value21); + this.processCount3(value20); + return; + case 95: + int value24 = this.calculateCount(); + int value25 = this.calculateCount(); + this.processCount3(value24); + this.processCount3(value25); + return; + case 97: + case 101: + case 105: + case 109: + case 113: + case 127: + case 129: + case 131: + this.processCount(4); + this.processCount3(4194308); + this.processCount3(4194304); + return; + case 99: + case 103: + case 107: + case 111: + case 115: + this.processCount(4); + this.processCount3(4194307); + this.processCount3(4194304); + return; + case 121: + case 123: + case 125: + this.processCount(3); + this.processCount3(4194308); + this.processCount3(4194304); + return; + case 132: + this.setLocal(value3, 4194305); + return; + case 133: + case 140: + this.processCount(1); + this.processCount3(4194308); + this.processCount3(4194304); + return; + case 134: + this.processCount(1); + this.processCount3(4194306); + return; + case 135: + case 141: + this.processCount(1); + this.processCount3(4194307); + this.processCount3(4194304); + return; + case 139: + case 190: + case 193: + this.processCount(1); + this.processCount3(4194305); + return; + case 148: + case 151: + case 152: + this.processCount(4); + this.processCount3(4194305); + return; + case 168: + case 169: + throw new IllegalArgumentException("JSR/RET are not supported with computeFrames option"); + case 178: + this.push(symbolTable, symbol.value); + return; + case 179: + this.pop(symbol.value); + return; + case 180: + this.processCount(1); + this.push(symbolTable, symbol.value); + return; + case 181: + this.pop(symbol.value); + this.calculateCount(); + return; + case 182: + case 183: + case 184: + case 185: + this.pop(symbol.value); + if (value2 != 184) { + int value26 = this.calculateCount(); + if (value2 == 183 && symbol.name.charAt(0) == '<') { + this.processCount2(value26); + } + } + this.push(symbolTable, symbol.value); + return; + case 186: + this.pop(symbol.value); + this.push(symbolTable, symbol.value); + return; + case 187: + this.processCount3(12582912 | symbolTable.addUninitializedType(symbol.value, value3)); + return; + case 188: + this.calculateCount(); + switch (value3) { + case 4: + this.processCount3(71303177); + return; + case 5: + this.processCount3(71303179); + return; + case 6: + this.processCount3(71303170); + return; + case 7: + this.processCount3(71303171); + return; + case 8: + this.processCount3(71303178); + return; + case 9: + this.processCount3(71303180); + return; + case 10: + this.processCount3(71303169); + return; + case 11: + this.processCount3(71303172); + return; + default: + throw new IllegalArgumentException(); + } + case 189: + String text; + String text2 = text = symbol.value; + this.calculateCount(); + if (text2.charAt(0) == '[') { + this.push(symbolTable, createText3(text)); + return; + } + this.processCount3(75497472 | symbolTable.addType(text)); + return; + case 192: + String text3; + String text4 = text3 = symbol.value; + this.calculateCount(); + if (text4.charAt(0) == '[') { + this.push(symbolTable, text3); + return; + } + this.processCount3(8388608 | symbolTable.addType(text3)); + return; + case 197: + this.processCount(value3); + this.push(symbolTable, symbol.value); + return; + } + } + + public final void setInputFrameFromApiFormat( + SymbolTable symbolTable, int value2, Object[] results, int value3, Object[] results2) { + int value4 = 0; + int value5; + for (int value6 = value5 = 0; value6 < value2; value6 = ++value5) { + int value7 = value5; + int value8 = value4; + int[] values = this.counts4; + value4++; + values[value8] = getAbstractTypeFromApiFormat(symbolTable, results[value7]); + if (results[value5] == Opcodes.INTEGER5 || results[value5] == Opcodes.INTEGER) { + int value9 = 4194304; + int value10 = value4; + int[] values2 = this.counts4; + value4++; + values2[value10] = value9; + } + } + for (int value11 = value4; value11 < this.counts4.length; value11 = value4) { + int value12 = 4194304; + int value13 = value4; + int[] values3 = this.counts4; + value4++; + values3[value13] = value12; + } + int value14 = 0; + int value15; + for (int value16 = value15 = 0; value16 < value3; value16 = ++value15) { + if (results2[value15] == Opcodes.INTEGER5 || results2[value15] == Opcodes.INTEGER) { + value14++; + } + } + this.counts5 = new int[value3 + value14]; + int value17 = 0; + int value18; + for (int value19 = value18 = 0; value19 < value3; value19 = ++value18) { + int value20 = value18; + int value21 = value17; + int[] values4 = this.counts5; + value17++; + values4[value21] = getAbstractTypeFromApiFormat(symbolTable, results2[value20]); + if (results2[value18] == Opcodes.INTEGER5 || results2[value18] == Opcodes.INTEGER) { + int value22 = 4194304; + int value23 = value17; + int[] values5 = this.counts5; + value17++; + values5[value23] = value22; + } + } + this.initializationCount = this.value = 0; + } + + public int getLocal(int value) { + if (this.counts3 != null && value < this.counts3.length) { + int value2; + if ((value2 = this.counts3[value]) == 0) { + value2 = this.counts3[value] = 20971520 | value; + } + return value2; + } else { + return 20971520 | value; + } + } + + public int getConcreteOutputType(int value, int value2) { + int value3 = value & -67108864; + int value4; + if ((value4 = value & 62914560) == 20971520) { + int value5 = value3 + this.counts4[value & 1048575]; + if ((value & 1048576) != 0 && (value5 == 4194308 || value5 == 4194307)) { + value5 = 4194304; + } + return value5; + } else { + if (value4 != 25165824) { + return value; + } + int value6 = value3 + this.counts5[value2 - (value & 1048575)]; + if ((value & 1048576) != 0 && (value6 == 4194308 || value6 == 4194307)) { + value6 = 4194304; + } + return value6; + } + } + + public final int getCounts5() { + return this.counts5.length; + } + + public void push(SymbolTable symbolTable, String text) { + int value = text.charAt(0) == '(' ? Type.getReturnTypeOffset(text) : 0; + int value2; + if ((value2 = getAbstractTypeFromDescriptor(symbolTable, text, value)) != 0) { + this.processCount3(value2); + if (value2 == 4194308 || value2 == 4194307) { + this.processCount3(4194304); + } + } + } + + public final void setInputFrameFromDescriptor( + SymbolTable symbolTable, int value, String text, int value2) { + int value3; + String text2; + label39: + { + this.counts4 = new int[value2]; + this.counts5 = new int[0]; + value3 = 0; + if ((value & 8) == 0) { + if ((value & 262144) == 0) { + int value4 = value3; + int[] values = this.counts4; + value3++; + text2 = text; + values[value4] = (int) 8388608 | symbolTable.addType(symbolTable.getClassName()); + break label39; + } + int value5 = 4194310; + int value6 = value3; + int[] values2 = this.counts4; + value3++; + values2[value6] = value5; + } + text2 = text; + } + Type[] types; + int value7 = (types = Type.getArgumentTypes(text2)).length; + int value8; + for (int value9 = value8 = 0; value9 < value7; value9 = ++value8) { + Type type = types[value8]; + int abstractTypeFromDescriptor = + getAbstractTypeFromDescriptor(symbolTable, type.getDescriptor(), 0); + int value10 = value3; + int[] values3 = this.counts4; + value3++; + values3[value10] = abstractTypeFromDescriptor; + if (abstractTypeFromDescriptor == 4194308 || abstractTypeFromDescriptor == 4194307) { + int value11 = 4194304; + int value12 = value3; + int[] values4 = this.counts4; + value3++; + values4[value12] = value11; + } + } + for (int value13 = value3; value13 < value2; value13 = value3) { + int value14 = 4194304; + int value15 = value3; + int[] values5 = this.counts4; + value3++; + values5[value15] = value14; + } + } + + public static void putAbstractType(SymbolTable symbolTable, int value2, ByteVector byteVector) { + int value3; + if ((value3 = (value2 & -67108864) >> 26) == 0) { + int value4 = value2 & 1048575; + switch (value2 & 62914560) { + case 4194304: + byteVector.putByte(value4); + return; + case 8388608: + byteVector + .putByte(7) + .putShort(symbolTable.getSymbol3(symbolTable.getSymbol2(value4).value).index); + return; + case 12582912: + byteVector.putByte(8).putShort((int) symbolTable.getSymbol2(value4).data); + return; + case 16777216: + byteVector.putByte(8); + symbolTable.getForwardUninitializedLabel(value4).put(byteVector); + return; + default: + throw new AssertionError(); + } + } else { + StringBuilder stringBuilder = new StringBuilder(); + int value5 = value3; + while (true) { + int value6 = value5; + value3--; + if (value6 <= 0) { + ByteVector byteVector2; + if ((value2 & 62914560) == 8388608) { + byteVector2 = byteVector; + stringBuilder + .append('L') + .append(symbolTable.getSymbol2(value2 & 1048575).value) + .append(';'); + } else { + switch (value2 & 1048575) { + case 1: + stringBuilder.append('I'); + byteVector2 = byteVector; + break; + case 2: + stringBuilder.append('F'); + byteVector2 = byteVector; + break; + case 3: + stringBuilder.append('D'); + byteVector2 = byteVector; + break; + case 4: + stringBuilder.append('J'); + byteVector2 = byteVector; + break; + case 5: + case 6: + case 7: + case 8: + default: + throw new AssertionError(); + case 9: + stringBuilder.append('Z'); + byteVector2 = byteVector; + break; + case 10: + stringBuilder.append('B'); + byteVector2 = byteVector; + break; + case 11: + stringBuilder.append('C'); + byteVector2 = byteVector; + break; + case 12: + stringBuilder.append('S'); + byteVector2 = byteVector; + } + } + byteVector2.putByte(7).putShort(symbolTable.getSymbol3(stringBuilder.toString()).index); + return; + } + value5 = value3; + stringBuilder.append('['); + } + } + } + + public void processCount2(int value) { + if (this.counts == null) { + this.counts = new int[2]; + } + int value2 = this.counts.length; + if (this.initializationCount >= value2) { + int[] values = new int[Math.max(this.initializationCount + 1, 2 * value2)]; + System.arraycopy(this.counts, 0, values, 0, value2); + this.counts = values; + } + this.counts[this.initializationCount++] = value; + } + + public static boolean merge(SymbolTable symbolTable, int value, int[] values, int value2) + throws ClassNotFoundException { + int value3; + if ((value3 = values[value2]) == value) { + return false; + } + int value4 = value; + if ((value & 67108863) == 4194309) { + if (value3 == 4194309) { + return false; + } + value4 = 4194309; + } + if (value3 == 0) { + values[value2] = value4; + return true; + } + int value5; + int value6; + if ((value3 & -67108864) == 0 && (value3 & 62914560) != 8388608) { + if (value3 == 4194309) { + value5 = (value4 & -67108864) == 0 && (value4 & 62914560) != 8388608 ? 4194304 : value4; + value6 = value5; + } else { + value6 = value5 = 4194304; + } + } else { + if (value4 == 4194309) { + return false; + } + if ((value4 & -4194304) == (value3 & -4194304)) { + value6 = + (value3 & 62914560) == 8388608 + ? (value5 = + value4 & -67108864 + | 8388608 + | symbolTable.addMergedType(value4 & 1048575, value3 & 1048575)) + : (value5 = + -67108864 + (value4 & -67108864) + | 8388608 + | symbolTable.addType("java/lang/Object")); + } else if ((value4 & -67108864) == 0 && (value4 & 62914560) != 8388608) { + value6 = value5 = 4194304; + } else { + int value7; + if ((value7 = value4 & -67108864) != 0 && (value4 & 62914560) != 8388608) { + value7 += -67108864; + } + int value8; + if ((value8 = value3 & -67108864) != 0 && (value3 & 62914560) != 8388608) { + value8 += -67108864; + } + value6 = + value5 = Math.min(value7, value8) | 8388608 | symbolTable.addType("java/lang/Object"); + } + } + if (value6 != value3) { + values[value2] = value5; + return true; + } else { + return false; + } + } + + public final void accept(MethodWriter methodWriter) { + int[] values = this.counts4; + int value = 0; + int value2 = 0; + int value3 = 0; + while (value3 < values.length) { + int value4 = values[value3]; + value3 += value4 != 4194308 && value4 != 4194307 ? 1 : 2; + if (value4 == 4194304) { + value2++; + } else { + value += value2 + 1; + value2 = 0; + } + } + int[] values2 = this.counts5; + int value5 = 0; + int value6; + for (int value7 = value6 = 0; value7 < values2.length; value7 = value6) { + int value8 = values2[value6]; + int value9 = value6 + (value8 != 4194308 && value8 != 4194307 ? 1 : 2); + value5++; + value6 = value9; + } + int value10 = methodWriter.visitFrameStart(this.owner.bytecodeOffset, value, value5); + int value11 = 0; + int value12 = value; + while (true) { + int value13 = value12; + value--; + if (value13 <= 0) { + int value14 = 0; + value12 = value5; + while (true) { + int value15 = value12; + value5--; + if (value15 <= 0) { + methodWriter.update4(); + return; + } + int value16 = values2[value14]; + value14 += value16 != 4194308 && value16 != 4194307 ? 1 : 2; + methodWriter.processCount6(value10, value16); + int value17 = value5; + value10++; + value12 = value17; + } + } + int value18 = values[value11]; + value11 += value18 != 4194308 && value18 != 4194307 ? 1 : 2; + methodWriter.processCount6(value10, value18); + int value19 = value; + value10++; + value12 = value19; + } + } + + public static int getAbstractTypeFromInternalName(SymbolTable symbolTable, String text) { + return 8388608 | symbolTable.addType(text); + } + + public static int getAbstractTypeFromApiFormat(SymbolTable symbolTable, Object result) { + if (result instanceof Integer) { + return 4194304 | (Integer) result; + } else if (result instanceof String) { + String descriptor = Type.getObjectType((String) result).getDescriptor(); + return getAbstractTypeFromDescriptor(symbolTable, descriptor, 0); + } else { + Label label; + return ((label = (Label) result).value3 & 4) != 0 + ? 12582912 | symbolTable.addUninitializedType("", label.bytecodeOffset) + : 16777216 | symbolTable.addForwardUninitializedType("", label); + } + } + + public void processCount3(int value3) { + if (this.counts2 == null) { + this.counts2 = new int[10]; + } + int value5 = this.counts2.length; + if (this.value >= value5) { + int[] values = new int[Math.max(this.value + 1, 2 * value5)]; + System.arraycopy(this.counts2, 0, values, 0, value5); + this.counts2 = values; + } + this.counts2[this.value++] = value3; + short value6; + if ((value6 = (short) (this.value2 + this.value)) > this.owner.value4) { + this.owner.value4 = value6; + } + } + + public static String createText3(String text) { + return "[" + text; + } + + public int getInitializedType(SymbolTable symbolTable, int value2) { + int value3; + if (value2 == 4194310 || (value2 & -4194304) == 12582912 || (value2 & -4194304) == 16777216) { + for (int value4 = value3 = 0; value4 < this.initializationCount; value4 = ++value3) { + int value5; + int value6 = (value5 = this.counts[value3]) & -67108864; + int value7 = value5 & 62914560; + int value8 = value5 & 1048575; + if (value7 == 20971520) { + value5 = value6 + this.counts4[value8]; + value4 = value2; + } else { + if (value7 == 25165824) { + value5 = value6 + this.counts5[this.counts5.length - value8]; + } + value4 = value2; + } + if (value4 == value5) { + if (value2 == 4194310) { + return 8388608 | symbolTable.addType(symbolTable.getClassName()); + } + return 8388608 | symbolTable.addType(symbolTable.getSymbol2(value2 & 1048575).value); + } + } + } + return value2; + } + + public static int getAbstractTypeFromDescriptor(SymbolTable symbolTable, String text, int value) { + switch (text.charAt(value)) { + case 'B': + case 'C': + case 'I': + case 'S': + case 'Z': + return 4194305; + case 'D': + return 4194307; + case 'E': + case 'G': + case 'H': + case 'K': + case 'M': + case 'N': + case 'O': + case 'P': + case 'Q': + case 'R': + case 'T': + case 'U': + case 'W': + case 'X': + case 'Y': + default: + throw new IllegalArgumentException(createText2(text.substring(value))); + case 'F': + return 4194306; + case 'J': + return 4194308; + case 'L': + String text2 = text.substring(value + 1, text.length() - 1); + return 8388608 | symbolTable.addType(text2); + case 'V': + return 0; + case '[': + int value2 = value + 1; + String text3 = text; + while (text3.charAt(value2) == '[') { + value2++; + text3 = text; + } + int value3; + int value4; + switch (text.charAt(value2)) { + case 'B': + value3 = 4194314; + value4 = value2; + break; + case 'C': + value3 = 4194315; + value4 = value2; + break; + case 'D': + value3 = 4194307; + value4 = value2; + break; + case 'E': + case 'G': + case 'H': + case 'K': + case 'M': + case 'N': + case 'O': + case 'P': + case 'Q': + case 'R': + case 'T': + case 'U': + case 'V': + case 'W': + case 'X': + case 'Y': + default: + throw new IllegalArgumentException(createText(text.substring(value2))); + case 'F': + value3 = 4194306; + value4 = value2; + break; + case 'I': + value3 = 4194305; + value4 = value2; + break; + case 'J': + value3 = 4194308; + value4 = value2; + break; + case 'L': + String text4 = text.substring(value2 + 1, text.length() - 1); + value3 = 8388608 | symbolTable.addType(text4); + value4 = value2; + break; + case 'S': + value3 = 4194316; + value4 = value2; + break; + case 'Z': + value3 = 4194313; + value4 = value2; + } + return value4 - value << 26 | value3; + } + } + + public final void copyFrom(Frame frame) { + this.counts4 = frame.counts4; + this.counts5 = frame.counts5; + this.value2 = 0; + this.counts3 = frame.counts3; + this.counts2 = frame.counts2; + this.value = frame.value; + this.initializationCount = frame.initializationCount; + this.counts = frame.counts; + } + + public final boolean merge(SymbolTable symbolTable, Frame frame, int value3) + throws ClassNotFoundException { + boolean matches = false; + int value4 = this.counts4.length; + int value5 = this.counts5.length; + if (frame.counts4 == null) { + int[] values = new int[value4]; + frame.counts4 = values; + matches = true; + } + int value6; + for (int value7 = value6 = 0; value7 < value4; value7 = value6) { + int value8; + if (this.counts3 != null && value6 < this.counts3.length) { + int value9; + if ((value9 = this.counts3[value6]) == 0) { + value8 = this.counts4[value6]; + } else { + value8 = this.getConcreteOutputType(value9, value5); + } + } else { + value8 = this.counts4[value6]; + } + if (this.counts != null) { + value8 = this.getInitializedType(symbolTable, value8); + } + int value10 = value6; + int[] values2 = frame.counts4; + int value11 = value8; + boolean matches2 = matches; + value6++; + matches = matches2 | merge(symbolTable, value11, values2, value10); + } + if (value3 <= 0) { + int value12 = this.counts5.length + this.value2; + if (frame.counts5 == null) { + int[] values3 = new int[value12 + this.value]; + frame.counts5 = values3; + matches = true; + } + int value13; + for (int value14 = value13 = 0; value14 < value12; value14 = value13) { + int value15 = this.counts5[value13]; + if (this.counts != null) { + value15 = this.getInitializedType(symbolTable, value15); + } + int value16 = value13; + int[] values4 = frame.counts5; + int value17 = value15; + boolean matches3 = matches; + value13++; + matches = matches3 | merge(symbolTable, value17, values4, value16); + } + int value18; + for (int value19 = value18 = 0; value19 < this.value; value19 = value18) { + int concreteOutputType = this.getConcreteOutputType(this.counts2[value18], value5); + if (this.counts != null) { + concreteOutputType = this.getInitializedType(symbolTable, concreteOutputType); + } + int value20 = value12 + value18; + int[] values5 = frame.counts5; + int value21 = concreteOutputType; + boolean matches4 = matches; + value18++; + matches = matches4 | merge(symbolTable, value21, values5, value20); + } + return matches; + } else { + int value22; + for (int value23 = value22 = 0; value23 < value4; value23 = value22) { + int value24 = this.counts4[value22]; + int value25 = value22; + int[] values6 = frame.counts4; + boolean matches5 = matches; + value22++; + matches = matches5 | merge(symbolTable, value24, values6, value25); + } + if (frame.counts5 == null) { + int[] values7 = new int[1]; + frame.counts5 = values7; + matches = true; + } + return matches | merge(symbolTable, value3, frame.counts5, 0); + } + } + + public void setLocal(int value, int value2) { + if (this.counts3 == null) { + this.counts3 = new int[10]; + } + int value3 = this.counts3.length; + if (value >= value3) { + int[] values; + int[] values2 = values = new int[Math.max(value + 1, 2 * value3)]; + System.arraycopy(this.counts3, 0, values, 0, value3); + this.counts3 = values2; + } + this.counts3[value] = value2; + } + + public void pop(String text) { + char value; + if ((value = text.charAt(0)) == '(') { + this.processCount((Type.getArgumentsAndReturnSizes(text) >> 2) - 1); + } else if (value != 'J' && value != 'D') { + this.processCount(1); + } else { + this.processCount(2); + } + } + + public int calculateCount() { + if (this.value > 0) { + return this.counts2[--this.value]; + } + this.value2--; + return 25165824 | -this.value2; + } +} diff --git a/src/main/java/com/allatori/lib/asm/Handle.java b/src/main/java/com/allatori/lib/asm/Handle.java new file mode 100644 index 0000000..a7aea1b --- /dev/null +++ b/src/main/java/com/allatori/lib/asm/Handle.java @@ -0,0 +1,76 @@ +package com.allatori.lib.asm; + +public final class Handle { + + public final boolean isInterface; + + public final String name; + + public final int tag; + + public final String descriptor; + + public final String owner; + + public String getOwner() { + return this.owner; + } + + public int getTag() { + return this.tag; + } + + public Handle(int tag, String owner, String name, String descriptor, boolean isInterface) { + super(); + this.tag = tag; + this.owner = owner; + this.name = name; + this.descriptor = descriptor; + this.isInterface = isInterface; + } + + @Override + public boolean equals(Object result) { + if (result == this) { + return true; + } + if (!(result instanceof Handle)) { + return false; + } + Handle handle = (Handle) result; + return this.tag == handle.tag + && this.isInterface == handle.isInterface + && this.owner.equals(handle.owner) + && this.name.equals(handle.name) + && this.descriptor.equals(handle.descriptor); + } + + @Deprecated + public Handle(int value, String text, String text2, String text3) { + this(value, text, text2, text3, value == 9); + } + + public String getName() { + return this.name; + } + + public String getDescriptor() { + return this.descriptor; + } + + public boolean isInterface() { + return this.isInterface; + } + + @Override + public int hashCode() { + return this.tag + + (this.isInterface ? 64 : 0) + + this.owner.hashCode() * this.name.hashCode() * this.descriptor.hashCode(); + } + + public static String stringConcat$0( + String text, String text2, String text3, int value, String text4) { + return "" + text + "." + text2 + text3 + " (" + value + text4 + ")"; + } +} diff --git a/src/main/java/com/allatori/lib/asm/Handler.java b/src/main/java/com/allatori/lib/asm/Handler.java new file mode 100644 index 0000000..e1614f9 --- /dev/null +++ b/src/main/java/com/allatori/lib/asm/Handler.java @@ -0,0 +1,84 @@ +package com.allatori.lib.asm; + +public final class Handler { + + public final String catchTypeDescriptor; + + public final int catchType; + + public final Label handlerPc; + + public Handler nextHandler; + + public final Label startPc; + + public final Label endPc; + + public static Handler removeRange(Handler handler, Label label, Label label2) { + if (handler == null) { + return null; + } + handler.nextHandler = removeRange(handler.nextHandler, label, label2); + int value = handler.startPc.bytecodeOffset; + int value2 = handler.endPc.bytecodeOffset; + int value3 = label.bytecodeOffset; + int value4 = label2 == null ? Integer.MAX_VALUE : label2.bytecodeOffset; + if (value3 >= value2 || value4 <= value) { + return handler; + } + if (value3 <= value) { + return value4 >= value2 ? handler.nextHandler : new Handler(handler, label2, handler.endPc); + } + if (value4 >= value2) { + return new Handler(handler, handler.startPc, label); + } + handler.nextHandler = new Handler(handler, label2, handler.endPc); + return new Handler(handler, handler.startPc, label); + } + + public static void putExceptionTable(Handler handler, ByteVector byteVector) { + byteVector.putShort(calculateCount(handler)); + Handler handler2 = handler; + for (Handler handler3 = handler2; handler3 != null; handler3 = handler2) { + byteVector + .putShort(handler2.startPc.bytecodeOffset) + .putShort(handler2.endPc.bytecodeOffset) + .putShort(handler2.handlerPc.bytecodeOffset) + .putShort(handler2.catchType); + handler2 = handler2.nextHandler; + } + } + + public static int calculateCount(Handler handler) { + int value = 0; + Handler handler2; + Handler handler3 = handler2 = handler; + while (handler3 != null) { + Handler handler4 = handler2.nextHandler; + Handler handler5 = handler2.nextHandler; + value++; + handler3 = handler5; + handler2 = handler4; + } + return value; + } + + public Handler( + Label label, Label label2, Label label3, int catchType, String catchTypeDescriptor) { + super(); + this.startPc = label; + this.endPc = label2; + this.handlerPc = label3; + this.catchType = catchType; + this.catchTypeDescriptor = catchTypeDescriptor; + } + + public static int calculateCount2(Handler handler) { + return 2 + 8 * calculateCount(handler); + } + + public Handler(Handler handler, Label label, Label label2) { + this(label, label2, handler.handlerPc, handler.catchType, handler.catchTypeDescriptor); + this.nextHandler = handler.nextHandler; + } +} diff --git a/src/main/java/com/allatori/lib/asm/Label.java b/src/main/java/com/allatori/lib/asm/Label.java new file mode 100644 index 0000000..d8b5ee9 --- /dev/null +++ b/src/main/java/com/allatori/lib/asm/Label.java @@ -0,0 +1,262 @@ +package com.allatori.lib.asm; + +public class Label { + + public static final int FLAG_DEBUG_ONLY = 1; + + public static final int FORWARD_REFERENCE_TYPE_MASK = -268435456; + + public static final int FLAG_JUMP_TARGET = 2; + + public static final int FORWARD_REFERENCES_CAPACITY_INCREMENT = 6; + + public Frame frame; + + public static final int FLAG_LINE_NUMBER = 128; + + public static final int FORWARD_REFERENCE_TYPE_SHORT = 268435456; + + public Edge outgoingEdges; + + public static final int FLAG_SUBROUTINE_START = 32; + + public short value; + + public short value2; + + public int[] counts; + + public static final int FORWARD_REFERENCE_TYPE_STACK_MAP = 805306368; + + public Label label; + + public int bytecodeOffset; + + public Object info; + + public static final Label EMPTY_LIST = new Label(); + + public short value3; + + public short value4; + + public static final int FORWARD_REFERENCE_HANDLE_MASK = 268435455; + + public Label label2; + + public static final int COUNT = 4; + + public static final int FLAG_SUBROUTINE_END = 64; + + public short value5; + + public static final int COUNT2 = 4; + + public static final int FLAG_SUBROUTINE_CALLER = 16; + + public int[] counts2; + + public static final int FLAG_REACHABLE = 8; + + public short value6; + + public static final int FORWARD_REFERENCE_TYPE_WIDE = 536870912; + + public static String stringConcat$0(int value) { + return "L" + value; + } + + public final void put(ByteVector byteVector) { + if ((this.value3 & 4) == 0) { + this.addForwardReference(0, 805306368, byteVector.length); + } + byteVector.putShort(this.bytecodeOffset); + } + + public int getOffset() { + if ((this.value3 & 4) == 0) { + throw new IllegalStateException("Label offset position has not been resolved yet"); + } else { + return this.bytecodeOffset; + } + } + + public void addForwardReference(int value, int value2, int value3) { + if (this.counts2 == null) { + this.counts2 = new int[6]; + } + int value4; + if ((value4 = this.counts2[0]) + 2 >= this.counts2.length) { + int[] values = new int[this.counts2.length + 6]; + System.arraycopy(this.counts2, 0, values, 0, this.counts2.length); + this.counts2 = values; + } + value4++; + int value5 = value4; + int[] values2 = this.counts2; + value4++; + values2[value5] = value; + this.counts2[value4] = value2 | value3; + this.counts2[0] = value4; + } + + public final void addSubroutineRetSuccessors(Label label2) { + Label label3 = EMPTY_LIST; + Label label4; + Label label5 = label4 = this; + this.label = EMPTY_LIST; + while (label5 != EMPTY_LIST) { + Label label6 = label4; + Label label7 = label4.label; + label4.label = label3; + label3 = label4; + if ((label4.value3 & 64) != 0 && label6.value2 != label2.value2) { + label6.outgoingEdges = + new Edge(label6.value5, label2.outgoingEdges.successor, label6.outgoingEdges); + } + label5 = label4 = label6.pushSuccessors(label7); + } + label5 = label3; + while (label5 != EMPTY_LIST) { + Label label8 = label3.label; + label3.label = null; + label5 = label3 = label8; + } + } + + public final void addLineNumber(int value2) { + if ((this.value3 & 128) == 0) { + this.value3 = (short) (this.value3 | 128); + this.value = (short) value2; + } else { + if (this.counts == null) { + this.counts = new int[4]; + } + int value4; + if ((value4 = ++this.counts[0]) >= this.counts.length) { + int[] values = new int[this.counts.length + 4]; + System.arraycopy(this.counts, 0, values, 0, this.counts.length); + this.counts = values; + } + this.counts[value4] = value2; + } + } + + public final Label getCanonicalInstance() { + return this.frame == null ? this : this.frame.owner; + } + + public final boolean resolve(byte[] values, ByteVector byteVector, int bytecodeOffset) { + this.value3 = (short) (this.value3 | 4); + this.bytecodeOffset = bytecodeOffset; + if (this.counts2 == null) { + return false; + } + boolean matches = false; + int value2; + for (int value4 = value2 = this.counts2[0]; value4 > 0; value4 = value2) { + int value5 = this.counts2[value2 - 1]; + int value6 = this.counts2[value2]; + int value7 = bytecodeOffset - value5; + int value8 = value6 & 268435455; + if ((value6 & -268435456) == 268435456) { + if (value7 < -32768 || value7 > 32767) { + int value9; + if ((value9 = values[value5] & 255) < 198) { + values[value5] = (byte) (value9 + 49); + } else { + values[value5] = (byte) (value9 + 20); + } + matches = true; + } + int value10 = value7 >>> 8; + int value11 = value8; + value8++; + values[value11] = (byte) value10; + values[value8] = (byte) value7; + } else if ((value6 & -268435456) == 536870912) { + int value12 = value7 >>> 24; + int value13 = value8; + value8++; + values[value13] = (byte) value12; + int value14 = value7 >>> 16; + int value15 = value8; + value8++; + values[value15] = (byte) value14; + int value16 = value7 >>> 8; + int value17 = value8; + value8++; + values[value17] = (byte) value16; + values[value8] = (byte) value7; + } else { + int value18 = bytecodeOffset >>> 8; + int value19 = value8; + byte[] values2 = byteVector.data; + value8++; + values2[value19] = (byte) value18; + byteVector.data[value8] = (byte) bytecodeOffset; + } + value2 -= 2; + } + return matches; + } + + public Label pushSuccessors(Label label2) { + Label label3 = label2; + Edge edge; + for (Edge edge2 = edge = this.outgoingEdges; edge2 != null; edge2 = edge = edge.nextEdge) { + int value = (this.value3 & 16) != 0 && edge == this.outgoingEdges.nextEdge ? 1 : 0; + if (value == 0 && edge.successor.label == null) { + edge.successor.label = label3; + label3 = edge.successor; + } + } + return label3; + } + + public final void accept(MethodVisitor methodVisitor, boolean matches) { + methodVisitor.visitLabel(this); + if (matches && (this.value3 & 128) != 0) { + methodVisitor.visitLineNumber(this.value & 65535, this); + int value2; + if (this.counts != null) { + for (int value4 = value2 = 1; value4 <= this.counts[0]; value4 = value2) { + int value5 = value2; + int[] values = this.counts; + value2++; + methodVisitor.visitLineNumber(values[value5], this); + } + } + } + } + + public final void put(ByteVector byteVector, int value, boolean matches) { + if ((this.value3 & 4) == 0) { + if (matches) { + this.addForwardReference(value, 536870912, byteVector.length); + byteVector.putInt(-1); + } else { + this.addForwardReference(value, 268435456, byteVector.length); + byteVector.putShort(-1); + } + } else if (matches) { + byteVector.putInt(this.bytecodeOffset - value); + } else { + byteVector.putShort(this.bytecodeOffset - value); + } + } + + public final void markSubroutine(short value) { + Label label2 = this; + this.label = EMPTY_LIST; + while (label2 != EMPTY_LIST) { + Label label3 = label2; + label2 = label2.label; + label3.label = null; + if (label3.value2 == 0) { + label3.value2 = value; + label2 = label3.pushSuccessors(label2); + } + } + } +} diff --git a/src/main/java/com/allatori/lib/asm/MethodTooLargeException.java b/src/main/java/com/allatori/lib/asm/MethodTooLargeException.java new file mode 100644 index 0000000..1abdd44 --- /dev/null +++ b/src/main/java/com/allatori/lib/asm/MethodTooLargeException.java @@ -0,0 +1,43 @@ +package com.allatori.lib.asm; + +public final class MethodTooLargeException extends IndexOutOfBoundsException { + + public final int codeSize; + + public final String className; + + public static final long serialVersionUID = 6807380416709738314L; + + public final String descriptor; + + public final String methodName; + + public static String stringConcat$0(String text, String text2, String text3) { + return "Method too large: " + text + "." + text2 + " " + text3; + } + + public String getDescriptor() { + return this.descriptor; + } + + public int getCodeSize() { + return this.codeSize; + } + + public String getClassName() { + return this.className; + } + + public String getMethodName() { + return this.methodName; + } + + public MethodTooLargeException( + String className, String methodName, String descriptor, int codeSize) { + super(stringConcat$0(className, methodName, descriptor)); + this.className = className; + this.methodName = methodName; + this.descriptor = descriptor; + this.codeSize = codeSize; + } +} diff --git a/src/main/java/com/allatori/lib/asm/MethodVisitor.java b/src/main/java/com/allatori/lib/asm/MethodVisitor.java new file mode 100644 index 0000000..aec5e5e --- /dev/null +++ b/src/main/java/com/allatori/lib/asm/MethodVisitor.java @@ -0,0 +1,282 @@ +package com.allatori.lib.asm; + +public abstract class MethodVisitor { + + public static final String TEXT = "This feature requires ASM5"; + + public final int api; + + public MethodVisitor mv; + + public AnnotationVisitor createAnnotationVisitor( + int value, TypePath typePath, String text, boolean matches) { + if (this.api < 327680) { + throw new UnsupportedOperationException("This feature requires ASM5"); + } else { + return this.mv != null + ? this.mv.createAnnotationVisitor(value, typePath, text, matches) + : null; + } + } + + public void visitFieldInsn(int value, String text, String text2, String text3) + throws ClassNotFoundException { + if (this.mv != null) { + this.mv.visitFieldInsn(value, text, text2, text3); + } + } + + public MethodVisitor getDelegate() { + return this.mv; + } + + public static String stringConcat$0(int value) { + return "Unsupported api " + value; + } + + public AnnotationVisitor visitParameterAnnotation(int value, String text, boolean matches) { + return this.mv != null ? this.mv.visitParameterAnnotation(value, text, matches) : null; + } + + public void visitTypeInsn(int value, String text) throws ClassNotFoundException { + if (this.mv != null) { + this.mv.visitTypeInsn(value, text); + } + } + + public void visitLabel(Label label) { + if (this.mv != null) { + this.mv.visitLabel(label); + } + } + + public void visitEnd() { + if (this.mv != null) { + this.mv.visitEnd(); + } + } + + public void visitCode() { + if (this.mv != null) { + this.mv.visitCode(); + } + } + + public void visitIntInsn(int value, int value2) throws ClassNotFoundException { + if (this.mv != null) { + this.mv.visitIntInsn(value, value2); + } + } + + public void visitMaxs(int value, int value2) throws ClassNotFoundException { + if (this.mv != null) { + this.mv.visitMaxs(value, value2); + } + } + + @Deprecated + public void visitMethodInsn(int value, String text, String text2, String text3) + throws ClassNotFoundException { + int value2 = value | (this.api < 327680 ? 256 : 0); + this.visitMethodInsn(value2, text, text2, text3, value == 185); + } + + public MethodVisitor(int api, MethodVisitor methodVisitor) { + super(); + if (api != 589824 + && api != 524288 + && api != 458752 + && api != 393216 + && api != 327680 + && api != 262144 + && api != 17432576) { + throw new IllegalArgumentException(stringConcat$0(api)); + } + if (api == 17432576) { + Constants.checkAsmExperimental(this); + } + this.api = api; + this.mv = methodVisitor; + } + + public AnnotationVisitor visitLocalVariableAnnotation( + int value, + TypePath typePath, + Label[] labels, + Label[] labels2, + int[] values, + String text, + boolean matches) { + if (this.api < 327680) { + throw new UnsupportedOperationException("This feature requires ASM5"); + } else { + return this.mv != null + ? this.mv.visitLocalVariableAnnotation( + value, typePath, labels, labels2, values, text, matches) + : null; + } + } + + public void visitTableSwitchInsn(int value, int value2, Label label, Label... label2) + throws ClassNotFoundException { + if (this.mv != null) { + this.mv.visitTableSwitchInsn(value, value2, label, (Label[]) label2); + } + } + + public void visitAttribute(Attribute attribute) { + if (this.mv != null) { + this.mv.visitAttribute(attribute); + } + } + + public AnnotationVisitor visitAnnotation(String text, boolean matches) { + return this.mv != null ? this.mv.visitAnnotation(text, matches) : null; + } + + public void visitLdcInsn(Object result) throws ClassNotFoundException { + if (this.api >= 327680 + || !(result instanceof Handle) + && (!(result instanceof Type) || ((Type) result).getSort() != 11)) { + if (this.api < 458752 && result instanceof ConstantDynamic) { + throw new UnsupportedOperationException("This feature requires ASM7"); + } + if (this.mv != null) { + this.mv.visitLdcInsn(result); + } + } else { + throw new UnsupportedOperationException("This feature requires ASM5"); + } + } + + public void visitLookupSwitchInsn(Label label, int[] values, Label[] labels) + throws ClassNotFoundException { + if (this.mv != null) { + this.mv.visitLookupSwitchInsn(label, values, labels); + } + } + + public AnnotationVisitor visitAnnotationDefault() { + return this.mv != null ? this.mv.visitAnnotationDefault() : null; + } + + public void visitLineNumber(int value, Label label) { + if (this.mv != null) { + this.mv.visitLineNumber(value, label); + } + } + + public AnnotationVisitor createAnnotationVisitor2( + int value, TypePath typePath, String text, boolean matches) { + if (this.api < 327680) { + throw new UnsupportedOperationException("This feature requires ASM5"); + } else { + return this.mv != null + ? this.mv.createAnnotationVisitor2(value, typePath, text, matches) + : null; + } + } + + public void visitParameter(String text, int value) { + if (this.api < 327680) { + throw new UnsupportedOperationException("This feature requires ASM5"); + } + if (this.mv != null) { + this.mv.visitParameter(text, value); + } + } + + public void visitFrame(int value, int value2, Object[] results, int value3, Object[] results2) { + if (this.mv != null) { + this.mv.visitFrame(value, value2, results, value3, results2); + } + } + + public void visitMultiANewArrayInsn(String text, int value) throws ClassNotFoundException { + if (this.mv != null) { + this.mv.visitMultiANewArrayInsn(text, value); + } + } + + public AnnotationVisitor createAnnotationVisitor3( + int value, TypePath typePath, String text, boolean matches) { + if (this.api < 327680) { + throw new UnsupportedOperationException("This feature requires ASM5"); + } else { + return this.mv != null + ? this.mv.createAnnotationVisitor3(value, typePath, text, matches) + : null; + } + } + + public void visitTryCatchBlock(Label label, Label label2, Label label3, String text) { + if (this.mv != null) { + this.mv.visitTryCatchBlock(label, label2, label3, text); + } + } + + public MethodVisitor(int value) { + this(value, null); + } + + public void visitInvokeDynamicInsn(String text, String text2, Handle handle, Object... result) + throws ClassNotFoundException { + if (this.api < 327680) { + throw new UnsupportedOperationException("This feature requires ASM5"); + } + if (this.mv != null) { + this.mv.visitInvokeDynamicInsn(text, text2, handle, (Object[]) result); + } + } + + public void visitIincInsn(int value, int value2) throws ClassNotFoundException { + if (this.mv != null) { + this.mv.visitIincInsn(value, value2); + } + } + + public void visitMethodInsn(int value, String text, String text2, String text3, boolean matches) + throws ClassNotFoundException { + if (this.api < 327680 && (value & 256) == 0) { + if (matches != (value == 185)) { + throw new UnsupportedOperationException("INVOKESPECIAL/STATIC on interfaces requires ASM5"); + } + this.visitMethodInsn(value, text, text2, text3); + } else { + if (this.mv != null) { + this.mv.visitMethodInsn(value & -257, text, text2, text3, (boolean) matches); + } + } + } + + public void visitAnnotableParameterCount(int value, boolean matches) { + if (this.mv != null) { + this.mv.visitAnnotableParameterCount(value, matches); + } + } + + public void visitInsn(int value) throws ClassNotFoundException { + if (this.mv != null) { + this.mv.visitInsn(value); + } + } + + public void visitVarInsn(int value, int value2) throws ClassNotFoundException { + if (this.mv != null) { + this.mv.visitVarInsn(value, value2); + } + } + + public void visitJumpInsn(int value, Label label) throws ClassNotFoundException { + if (this.mv != null) { + this.mv.visitJumpInsn(value, label); + } + } + + public void visitLocalVariable( + String text, String text2, String text3, Label label, Label label2, int value) { + if (this.mv != null) { + this.mv.visitLocalVariable(text, text2, text3, label, label2, value); + } + } +} diff --git a/src/main/java/com/allatori/lib/asm/MethodWriter.java b/src/main/java/com/allatori/lib/asm/MethodWriter.java new file mode 100644 index 0000000..ce0dcb1 --- /dev/null +++ b/src/main/java/com/allatori/lib/asm/MethodWriter.java @@ -0,0 +1,1721 @@ +package com.allatori.lib.asm; + +public final class MethodWriter extends MethodVisitor { + + public Attribute attribute; + + public final SymbolTable symbolTable; + + public int count; + + public int count2; + + public AnnotationWriter[] annotationWriters; + + public int count3; + + public final int numberOfExceptions; + + public int[] counts; + + public final int[] exceptionIndexTable; + + public final int descriptorIndex; + + public int count4; + + public AnnotationWriter[] annotationWriters2; + + public int[] counts2; + + public static final int COMPUTE_INSERTED_FRAMES = 3; + + public int count5; + + public int count6; + + public ByteVector byteVector; + + public int count7; + + public final int nameIndex; + + public ByteVector byteVector2; + + public ByteVector byteVector3; + + public static final int[] STACK_SIZE_DELTA = + new int[] { + 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 2, 2, 1, 1, 1, 0, 0, 1, 2, 1, 2, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, 0, -1, -1, -1, -1, -1, -2, -1, -2, + -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, -4, -3, -4, -3, -3, -3, + -3, -1, -2, 1, 1, 1, 2, 2, 2, 0, -1, -2, -1, -2, -1, -2, -1, -2, -1, -2, -1, -2, -1, -2, -1, + -2, -1, -2, -1, -2, 0, 0, 0, 0, -1, -1, -1, -1, -1, -1, -1, -2, -1, -2, -1, -2, 0, 1, 0, 1, + -1, -1, 0, 0, 1, 1, -1, 0, -1, 0, 0, 0, -3, -1, -1, -3, -3, -1, -1, -1, -1, -1, -1, -2, -2, + -2, -2, -2, -2, -2, -2, 0, 1, 0, -1, -1, -1, -2, -1, -2, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, -1, -1, 0, 0 + }; + + public final ByteVector code; + + public int maxLocals; + + public static final int COMPUTE_MAX_STACK_AND_LOCAL = 1; + + public int count8; + + public final int signatureIndex; + + public static final int COUNT = 0; + + public Attribute attribute2; + + public boolean enabled; + + public ByteVector byteVector4; + + public Handler handler; + + public AnnotationWriter annotationWriter; + + public int count9; + + public final int accessFlags; + + public ByteVector byteVector5; + + public final String name; + + public Handler handler2; + + public AnnotationWriter annotationWriter2; + + public int count10; + + public boolean enabled2; + + public int count11; + + public Label label; + + public AnnotationWriter annotationWriter3; + + public AnnotationWriter annotationWriter4; + + public ByteVector byteVector6; + + public static final int COUNT2 = 0; + + public AnnotationWriter annotationWriter5; + + public final int compute; + + public Label firstBasicBlock; + + public int count12; + + public static final int COMPUTE_ALL_FRAMES = 4; + + public AnnotationWriter annotationWriter6; + + public int currentLocals; + + public int count13; + + public Label label2; + + public final String descriptor; + + public int count14; + + public static final int COMPUTE_MAX_STACK_AND_LOCAL_FROM_FRAMES = 2; + + @Override + public void visitFrame( + int value, int currentLocals, Object[] results, int count9, Object[] results2) { + if (this.compute != 4) { + MethodWriter methodWriter; + if (this.compute == 3) { + if (this.label.frame == null) { + methodWriter = this; + this.label.frame = new CurrentFrame(this.label); + this.label.frame.setInputFrameFromDescriptor( + this.symbolTable, this.accessFlags, this.descriptor, currentLocals); + this.label.frame.accept(this); + } else { + if (value == -1) { + this.label.frame.setInputFrameFromApiFormat( + this.symbolTable, currentLocals, results, count9, results2); + } + methodWriter = this; + this.label.frame.accept(this); + } + } else if (value == -1) { + if (this.counts2 == null) { + int value4 = Type.getArgumentsAndReturnSizes(this.descriptor) >> 2; + Frame frame2 = new Frame(new Label()); + frame2.setInputFrameFromDescriptor( + this.symbolTable, this.accessFlags, this.descriptor, value4); + frame2.accept(this); + } + this.currentLocals = currentLocals; + int value5 = this.visitFrameStart(this.code.length, currentLocals, count9); + int value6; + for (int value7 = value6 = 0; value7 < currentLocals; value7 = value6) { + SymbolTable symbolTable2 = this.symbolTable; + int value8 = value5; + int[] values = this.counts; + value5++; + int abstractTypeFromApiFormat = + Frame.getAbstractTypeFromApiFormat(symbolTable2, results[value6]); + value6++; + values[value8] = abstractTypeFromApiFormat; + } + int value9; + for (int value10 = value9 = 0; value10 < count9; value10 = value9) { + SymbolTable symbolTable3 = this.symbolTable; + int value11 = value5; + int[] values2 = this.counts; + value5++; + int abstractTypeFromApiFormat2 = + Frame.getAbstractTypeFromApiFormat(symbolTable3, results2[value9]); + value9++; + values2[value11] = abstractTypeFromApiFormat2; + } + methodWriter = this; + this.update4(); + } else { + if (this.symbolTable.getCount() < 50) { + throw new IllegalArgumentException("Class versions V1_5 or less must use F_NEW frames."); + } + int value12; + int value13; + if (this.byteVector2 == null) { + this.byteVector2 = new ByteVector(); + value12 = this.code.length; + value13 = value; + } else { + if ((value12 = this.code.length - this.count3 - 1) < 0) { + if (value == 3) { + return; + } + throw new IllegalStateException(); + } + value13 = value; + } + label130: + { + switch (value13) { + case 0: + this.currentLocals = currentLocals; + this.byteVector2.putByte(255).putShort(value12).putShort(currentLocals); + int value14 = 0; + for (int value15 = value14; value15 < currentLocals; value15 = value14) { + int value16 = value14; + value14++; + this.processValue(results[value16]); + } + this.byteVector2.putShort(count9); + int value17 = 0; + for (int value18 = value17; value18 < count9; value18 = value17) { + int value19 = value17; + value17++; + this.processValue(results2[value19]); + } + break; + case 1: + this.currentLocals += currentLocals; + this.byteVector2.putByte(251 + currentLocals).putShort(value12); + int value20 = 0; + for (int value21 = value20; value21 < currentLocals; value21 = value20) { + int value22 = value20; + value20++; + this.processValue(results[value22]); + } + break; + case 2: + methodWriter = this; + this.currentLocals -= currentLocals; + this.byteVector2.putByte(251 - currentLocals).putShort(value12); + break label130; + case 3: + if (value12 < 64) { + methodWriter = this; + this.byteVector2.putByte(value12); + } else { + methodWriter = this; + this.byteVector2.putByte(251).putShort(value12); + } + break label130; + case 4: + if (value12 < 64) { + methodWriter = this; + this.byteVector2.putByte(64 + value12); + } else { + methodWriter = this; + this.byteVector2.putByte(247).putShort(value12); + } + methodWriter.processValue(results2[0]); + methodWriter = this; + break label130; + default: + throw new IllegalArgumentException(); + } + methodWriter = this; + } + methodWriter.count3 = this.code.length; + methodWriter = this; + this.count7++; + } + if (methodWriter.compute == 2) { + int value23 = 0; + this.count9 = count9; + for (int index = 0; value23 < count9; value23 = ++index) { + if (results2[index] == Opcodes.INTEGER5 || results2[index] == Opcodes.INTEGER) { + this.count9++; + } + } + if (this.count9 > this.count14) { + this.count14 = this.count9; + } + } + this.count = Math.max(this.count, count9); + this.maxLocals = Math.max(this.maxLocals, this.currentLocals); + } + } + + @Override + public void visitTryCatchBlock(Label label, Label label2, Label label3, String string) { + MethodWriter methodWriter; + String string2; + int n; + if (string != null) { + n = this.symbolTable.getSymbol3((String) string).index; + string2 = string; + } else { + n = 0; + string2 = string; + } + Handler handler = new Handler(label, label2, label3, n, string2); + if (this.handler2 == null) { + methodWriter = this; + this.handler2 = handler; + } else { + methodWriter = this; + this.handler.nextHandler = handler; + } + methodWriter.handler = handler; + } + + public void visitSwitchInsn(Label label2, Label[] labels) throws ClassNotFoundException { + if (this.label != null) { + if (this.compute == 4) { + this.label.frame.execute(171, 0, null, null); + this.processLabel3(0, label2); + Label canonicalInstance = label2.getCanonicalInstance(); + canonicalInstance.value3 = (short) (canonicalInstance.value3 | 2); + int value = labels.length; + int value2; + for (int value4 = value2 = 0; value4 < value; value4 = value2) { + Label label3 = labels[value2]; + this.processLabel3(0, label3); + Label canonicalInstance2 = label3.getCanonicalInstance(); + short value5 = canonicalInstance2.value3; + value2++; + canonicalInstance2.value3 = (short) (value5 | (byte) 2); + } + } else if (this.compute == 1) { + this.count9--; + this.processLabel3(this.count9, label2); + int value6 = labels.length; + int value7; + for (int value8 = value7 = 0; value8 < value6; value8 = value7) { + Label label4 = labels[value7]; + value7++; + this.processLabel3(this.count9, label4); + } + } + this.update3(); + } + } + + @Override + public void visitInsn(int value) throws ClassNotFoundException { + this.count8 = this.code.length; + this.code.putByte(value); + if (this.label != null) { + int value2; + if (this.compute != 4 && this.compute != 3) { + int value3; + if ((value3 = this.count9 + STACK_SIZE_DELTA[value]) > this.count14) { + this.count14 = value3; + } + this.count9 = value3; + value2 = value; + } else { + this.label.frame.execute(value, 0, null, null); + value2 = value; + } + if (value2 >= 172 && value <= 177 || value == 191) { + this.update3(); + } + } + } + + @Override + public void visitAttribute(Attribute attribute3) { + if (attribute3.isEnabled2()) { + attribute3.nextAttribute = this.attribute2; + this.attribute2 = attribute3; + } else { + attribute3.nextAttribute = this.attribute; + this.attribute = attribute3; + } + } + + @Override + public void visitLocalVariable( + String text, String text2, String text3, Label label, Label label2, int value) { + if (text3 != null) { + if (this.byteVector3 == null) { + this.byteVector3 = new ByteVector(); + } + this.count11++; + this.byteVector3 + .putShort(label.bytecodeOffset) + .putShort(label2.bytecodeOffset - label.bytecodeOffset) + .putShort(this.symbolTable.addConstantUtf8(text)) + .putShort(this.symbolTable.addConstantUtf8(text3)) + .putShort(value); + } + if (this.byteVector5 == null) { + this.byteVector5 = new ByteVector(); + } + this.count13++; + this.byteVector5 + .putShort(label.bytecodeOffset) + .putShort(label2.bytecodeOffset - label.bytecodeOffset) + .putShort(this.symbolTable.addConstantUtf8(text)) + .putShort(this.symbolTable.addConstantUtf8(text2)) + .putShort(value); + if (this.compute != 0) { + char value2 = text2.charAt(0); + int value3; + if ((value3 = value + (value2 != 'J' && value2 != 'D' ? 1 : 2)) > this.maxLocals) { + this.maxLocals = value3; + } + } + } + + @Override + public void visitEnd() {} + + public boolean isCount7() { + return this.count7 > 0; + } + + @Override + public void visitParameter(String text, int value) { + if (this.byteVector6 == null) { + this.byteVector6 = new ByteVector(); + } + this.count6++; + this.byteVector6 + .putShort(text == null ? 0 : this.symbolTable.addConstantUtf8(text)) + .putShort(value); + } + + @Override + public void visitAnnotableParameterCount(int value, boolean matches) { + if (matches) { + this.count4 = value; + } else { + this.count10 = value; + } + } + + @Override + public void visitLabel(Label label3) { + this.enabled2 = + this.enabled2 | label3.resolve(this.code.data, this.byteVector2, this.code.length); + if ((label3.value3 & 1) == 0) { + if (this.compute == 4) { + if (this.label != null) { + if (label3.bytecodeOffset == this.label.bytecodeOffset) { + this.label.value3 = (short) (this.label.value3 | label3.value3 & 2); + label3.frame = this.label.frame; + return; + } + this.processLabel3(0, label3); + } + if (this.label2 != null) { + if (label3.bytecodeOffset == this.label2.bytecodeOffset) { + this.label2.value3 = (short) (this.label2.value3 | label3.value3 & 2); + label3.frame = this.label2.frame; + this.label = this.label2; + return; + } + this.label2.label2 = label3; + } + this.label = this.label2 = label3; + label3.frame = new Frame(label3); + } else if (this.compute == 3) { + if (this.label == null) { + this.label = label3; + } else { + this.label.frame.owner = label3; + } + } else if (this.compute == 1) { + if (this.label != null) { + this.label.value4 = (short) this.count14; + this.processLabel3(this.count9, label3); + } + this.label = label3; + this.count9 = 0; + this.count14 = 0; + if (this.label2 != null) { + this.label2.label2 = label3; + } + this.label2 = label3; + } else { + if (this.compute == 2 && this.label == null) { + this.label = label3; + } + } + } + } + + public void processCount5(int value, int value2) { + int value3; + for (int value4 = value3 = value; value4 < value2; value4 = value3) { + int value5 = this.counts[value3]; + SymbolTable symbolTable2 = this.symbolTable; + value3++; + Frame.putAbstractType(symbolTable2, value5, this.byteVector2); + } + } + + @Override + public AnnotationVisitor createAnnotationVisitor3( + int value, TypePath typePath, String text, boolean matches) { + return matches + ? (this.annotationWriter = + AnnotationWriter.create( + this.symbolTable, + value & -16776961 | this.count8 << 8, + typePath, + text, + this.annotationWriter)) + : (this.annotationWriter6 = + AnnotationWriter.create( + this.symbolTable, + value & -16776961 | this.count8 << 8, + typePath, + text, + this.annotationWriter6)); + } + + @Override + public void visitMaxs(int count, int maxLocals) throws ClassNotFoundException { + if (this.compute == 4) { + this.computeAllFrames(); + } else if (this.compute == 1) { + this.computeMaxStackAndLocal(); + } else if (this.compute == 2) { + this.count = this.count14; + } else { + this.count = count; + this.maxLocals = maxLocals; + } + } + + public void processCount6(int value, int value2) { + this.counts[value] = value2; + } + + public boolean canCopyMethodAttributes( + ClassReader classReader, + boolean matches, + boolean matches2, + int value, + int value2, + int value3) { + if (classReader == this.symbolTable.getSource() + && value == this.descriptorIndex + && value2 == this.signatureIndex + && matches2 == ((this.accessFlags & 131072) != 0)) { + boolean matches3 = this.symbolTable.getCount() < 49 && (this.accessFlags & 4096) != 0; + if (matches != matches3) { + return false; + } + if (value3 == 0) { + if (this.numberOfExceptions != 0) { + return false; + } + } else if (classReader.readUnsignedShort(value3) == this.numberOfExceptions) { + int value4 = value3 + 2; + int value5; + for (int value6 = value5 = 0; value6 < this.numberOfExceptions; value6 = ++value5) { + if (classReader.readUnsignedShort(value4) != this.exceptionIndexTable[value5]) { + return false; + } + value4 += 2; + } + } + return true; + } else { + return false; + } + } + + public int visitFrameStart(int value, int value2, int value3) { + int value4 = 3 + value2 + value3; + if (this.counts == null || this.counts.length < value4) { + this.counts = new int[value4]; + } + this.counts[0] = value; + this.counts[1] = value2; + this.counts[2] = value3; + return 3; + } + + @Override + public void visitIincInsn(int value, int value2) throws ClassNotFoundException { + this.count8 = this.code.length; + MethodWriter methodWriter; + if (value <= 255 && value2 <= 127 && value2 >= -128) { + methodWriter = this; + this.code.putByte(132).put11(value, value2); + } else { + methodWriter = this; + this.code.putByte(196).put12(132, value).putShort(value2); + } + if (methodWriter.label != null && (this.compute == 4 || this.compute == 3)) { + this.label.frame.execute(132, value, null, null); + } + int value3; + if (this.compute != 0 && (value3 = value + 1) > this.maxLocals) { + this.maxLocals = value3; + } + } + + @Override + public void visitMethodInsn(int value, String text, String text2, String text3, boolean matches) + throws ClassNotFoundException { + this.count8 = this.code.length; + Symbol symbol = this.symbolTable.addConstantMethodref(text, text2, text3, matches); + MethodWriter methodWriter; + if (value == 185) { + methodWriter = this; + this.code.put12(185, symbol.index).put11(symbol.getArgumentsAndReturnSizes() >> 2, 0); + } else { + methodWriter = this; + this.code.put12(value, symbol.index); + } + if (methodWriter.label != null) { + if (this.compute == 4 || this.compute == 3) { + this.label.frame.execute(value, 0, symbol, this.symbolTable); + return; + } + int value2; + int value3 = ((value2 = symbol.getArgumentsAndReturnSizes()) & 3) - (value2 >> 2); + int value4; + if ((value == 184 ? (value4 = this.count9 + value3 + 1) : (value4 = this.count9 + value3)) + > this.count14) { + this.count14 = value4; + } + this.count9 = value4; + } + } + + @Override + public void visitLineNumber(int value, Label label) { + if (this.byteVector4 == null) { + this.byteVector4 = new ByteVector(); + } + this.count12++; + this.byteVector4.putShort(label.bytecodeOffset); + this.byteVector4.putShort(value); + } + + public void computeMaxStackAndLocal() { + Handler handler; + for (Handler handler3 = handler = this.handler2; + handler3 != null; + handler3 = handler = handler.nextHandler) { + Label label3 = handler.handlerPc; + Label label4 = handler.startPc; + Label label5 = handler.endPc; + Label label6 = label4; + while (label6 != label5) { + Label label7; + if ((label4.value3 & 16) == 0) { + label7 = label4; + label4.outgoingEdges = new Edge(Integer.MAX_VALUE, label3, label4.outgoingEdges); + } else { + label7 = label4; + label4.outgoingEdges.nextEdge.nextEdge = + new Edge(Integer.MAX_VALUE, label3, label4.outgoingEdges.nextEdge.nextEdge); + } + label6 = label4 = label7.label2; + } + } + if (this.enabled) { + int value = 1; + int value5 = 1; + this.firstBasicBlock.markSubroutine((short) value); + Label label8; + for (int index = 1; value5 <= value; value5 = ++index) { + for (Label label9 = label8 = this.firstBasicBlock; + label9 != null; + label9 = label8 = label8.label2) { + if ((label8.value3 & 16) != 0 && label8.value2 == index) { + Label label10 = label8.outgoingEdges.nextEdge.successor; + if (label8.outgoingEdges.nextEdge.successor.value2 == 0) { + label10.markSubroutine((short) (++value)); + } + } + } + } + Label label11; + for (Label label12 = label11 = this.firstBasicBlock; + label12 != null; + label12 = label11 = label11.label2) { + if ((label11.value3 & 16) != 0) { + label11.outgoingEdges.nextEdge.successor.addSubroutineRetSuccessors(label11); + } + } + } + Label label13 = this.firstBasicBlock; + this.firstBasicBlock.label = Label.EMPTY_LIST; + int value7 = this.count; + while (label13 != Label.EMPTY_LIST) { + Label label14 = label13; + label13 = label13.label; + short value8 = label14.value6; + int value9; + if ((value9 = label14.value6 + label14.value4) > value7) { + value7 = value9; + } + Edge edge = label14.outgoingEdges; + if ((label14.value3 & 16) != 0) { + edge = edge.nextEdge; + } + for (Edge edge2 = edge; edge2 != null; edge2 = edge = edge.nextEdge) { + Label label15 = edge.successor; + if (edge.successor.label == null) { + label15.value6 = (short) (edge.info == Integer.MAX_VALUE ? 1 : value8 + edge.info); + label15.label = label13; + label13 = label15; + } + } + } + this.count = value7; + } + + @Override + public void visitTypeInsn(int value, String text) throws ClassNotFoundException { + this.count8 = this.code.length; + Symbol symbol3 = this.symbolTable.getSymbol3(text); + this.code.put12(value, symbol3.index); + if (this.label != null) { + if (this.compute == 4 || this.compute == 3) { + this.label.frame.execute(value, this.count8, symbol3, this.symbolTable); + return; + } + if (value == 187) { + int value2; + if ((value2 = this.count9 + 1) > this.count14) { + this.count14 = value2; + } + this.count9 = value2; + } + } + } + + @Override + public void visitJumpInsn(int value, Label label2) throws ClassNotFoundException { + Label label3; + this.count8 = this.code.length; + int value2 = value >= 200 ? value - 33 : value; + boolean matches = false; + MethodWriter methodWriter; + if ((label2.value3 & 4) != 0 && label2.bytecodeOffset - this.code.length < -32768) { + Label label4; + if (value2 == 167) { + label4 = label2; + this.code.putByte(200); + } else if (value2 == 168) { + label4 = label2; + this.code.putByte(201); + } else { + this.code.putByte(value2 >= 198 ? value2 ^ 1 : (value2 + 1 ^ 1) - 1); + this.code.putShort(8); + this.code.putByte(220); + matches = this.enabled2 = true; + label4 = label2; + } + label4.put(this.code, this.code.length - 1, true); + methodWriter = this; + } else if (value2 != value) { + this.code.putByte(value); + methodWriter = this; + label2.put(this.code, this.code.length - 1, true); + } else { + methodWriter = this; + this.code.putByte(value2); + label2.put(this.code, this.code.length - 1, false); + } + if (methodWriter.label != null) { + Label label5; + label65: + { + label5 = null; + if (this.compute == 4) { + this.label.frame.execute(value2, 0, null, null); + Label canonicalInstance = label2.getCanonicalInstance(); + canonicalInstance.value3 = (short) (canonicalInstance.value3 | 2); + this.processLabel3(0, label2); + if (value2 != 167) { + label3 = label5 = new Label(); + break label65; + } + } else { + if (this.compute == 3) { + label3 = label5; + this.label.frame.execute(value2, 0, null, null); + break label65; + } + if (this.compute == 2) { + label3 = label5; + this.count9 = this.count9 + STACK_SIZE_DELTA[value2]; + break label65; + } + if (value2 == 168) { + if ((label2.value3 & 32) == 0) { + label2.value3 = (short) (label2.value3 | 32); + this.enabled = true; + } + this.label.value3 = (short) (this.label.value3 | 16); + this.processLabel3(this.count9 + 1, label2); + label3 = label5 = new Label(); + break label65; + } + this.count9 = this.count9 + STACK_SIZE_DELTA[value2]; + this.processLabel3(this.count9, label2); + } + label3 = label5; + } + if (label3 != null) { + if (matches) { + label5.value3 = (short) (label5.value3 | 2); + } + this.visitLabel(label5); + } + if (value2 == 167) { + this.update3(); + } + } + } + + public void update3() { + if (this.compute == 4) { + Label label3 = new Label(); + label3.frame = new Frame(label3); + label3.resolve(this.code.data, this.byteVector2, this.code.length); + this.label2 = this.label2.label2 = label3; + this.label = null; + } else { + if (this.compute == 1) { + this.label.value4 = (short) this.count14; + this.label = null; + } + } + } + + public void putMethodInfo(ByteVector byteVector7) { + int value = this.symbolTable.getCount() < 49 ? 1 : 0; + int value2 = value != 0 ? 4096 : 0; + byteVector7 + .putShort(this.accessFlags & ~value2) + .putShort(this.nameIndex) + .putShort(this.descriptorIndex); + if (this.count2 != 0) { + byteVector7.putByteArray( + this.symbolTable.getSource().classFileBuffer, this.count2, this.count5); + } else { + int value3 = 0; + if (this.code.length > 0) { + value3++; + } + if (this.numberOfExceptions > 0) { + value3++; + } + if ((this.accessFlags & 4096) != 0 && value != 0) { + value3++; + } + if (this.signatureIndex != 0) { + value3++; + } + if ((this.accessFlags & 131072) != 0) { + value3++; + } + if (this.annotationWriter5 != null) { + value3++; + } + if (this.annotationWriter4 != null) { + value3++; + } + if (this.annotationWriters != null) { + value3++; + } + if (this.annotationWriters2 != null) { + value3++; + } + if (this.annotationWriter3 != null) { + value3++; + } + if (this.annotationWriter2 != null) { + value3++; + } + if (this.byteVector != null) { + value3++; + } + if (this.byteVector6 != null) { + value3++; + } + if (this.attribute != null) { + value3 += this.attribute.getAttributeCount(); + } + byteVector7.putShort(value3); + if (this.code.length > 0) { + int value4 = 10 + this.code.length + Handler.calculateCount2(this.handler2); + int value5 = 0; + if (this.byteVector2 != null) { + int value6 = this.byteVector2.length; + int value7 = value4; + value5++; + value4 = value7 + (byte) 8 + value6; + } + if (this.byteVector4 != null) { + int value8 = this.byteVector4.length; + int value9 = value4; + value5++; + value4 = value9 + (byte) 8 + value8; + } + if (this.byteVector5 != null) { + int value10 = this.byteVector5.length; + int value11 = value4; + value5++; + value4 = value11 + (byte) 8 + value10; + } + if (this.byteVector3 != null) { + int value12 = this.byteVector3.length; + int value13 = value4; + value5++; + value4 = value13 + (byte) 8 + value12; + } + if (this.annotationWriter != null) { + AnnotationWriter annotationWriter7 = this.annotationWriter; + int value14 = value4; + value5++; + value4 = + value14 + + annotationWriter7.computeAnnotationsSize( + (String) "RuntimeVisibleTypeAnnotations"); + } + if (this.annotationWriter6 != null) { + AnnotationWriter annotationWriter8 = this.annotationWriter6; + int value15 = value4; + value5++; + value4 = + value15 + + annotationWriter8.computeAnnotationsSize( + (String) "RuntimeInvisibleTypeAnnotations"); + } + if (this.attribute2 != null) { + value4 += + this.attribute2.computeAttributesSize( + this.symbolTable, this.code.data, this.code.length, this.count, this.maxLocals); + value5 += this.attribute2.getAttributeCount(); + } + byteVector7 + .putShort(this.symbolTable.addConstantUtf8("Code")) + .putInt(value4) + .putShort(this.count) + .putShort(this.maxLocals) + .putInt(this.code.length) + .putByteArray(this.code.data, 0, this.code.length); + Handler.putExceptionTable(this.handler2, byteVector7); + byteVector7.putShort(value5); + if (this.byteVector2 != null) { + int value16 = this.symbolTable.getCount() >= 50 ? 1 : 0; + byteVector7 + .putShort( + this.symbolTable.addConstantUtf8(value16 != 0 ? "StackMapTable" : "StackMap")) + .putInt(2 + this.byteVector2.length) + .putShort(this.count7) + .putByteArray(this.byteVector2.data, 0, this.byteVector2.length); + } + if (this.byteVector4 != null) { + byteVector7 + .putShort(this.symbolTable.addConstantUtf8("LineNumberTable")) + .putInt(2 + this.byteVector4.length) + .putShort(this.count12) + .putByteArray(this.byteVector4.data, 0, this.byteVector4.length); + } + if (this.byteVector5 != null) { + byteVector7 + .putShort(this.symbolTable.addConstantUtf8("LocalVariableTable")) + .putInt(2 + this.byteVector5.length) + .putShort(this.count13) + .putByteArray(this.byteVector5.data, 0, this.byteVector5.length); + } + if (this.byteVector3 != null) { + byteVector7 + .putShort(this.symbolTable.addConstantUtf8("LocalVariableTypeTable")) + .putInt(2 + this.byteVector3.length) + .putShort(this.count11) + .putByteArray(this.byteVector3.data, 0, this.byteVector3.length); + } + if (this.annotationWriter != null) { + this.annotationWriter.putAnnotations( + this.symbolTable.addConstantUtf8("RuntimeVisibleTypeAnnotations"), byteVector7); + } + if (this.annotationWriter6 != null) { + this.annotationWriter6.putAnnotations( + this.symbolTable.addConstantUtf8("RuntimeInvisibleTypeAnnotations"), byteVector7); + } + if (this.attribute2 != null) { + this.attribute2.putAttributes( + this.symbolTable, + this.code.data, + this.code.length, + this.count, + this.maxLocals, + byteVector7); + } + } + if (this.numberOfExceptions > 0) { + byteVector7 + .putShort(this.symbolTable.addConstantUtf8("Exceptions")) + .putInt(2 + 2 * this.numberOfExceptions) + .putShort(this.numberOfExceptions); + int[] values = this.exceptionIndexTable; + int value17 = values.length; + int value18; + for (int value19 = value18 = 0; value19 < value17; value19 = value18) { + int value20 = value18; + value18++; + byteVector7.putShort(values[value20]); + } + } + Attribute.putAttributes(this.symbolTable, this.accessFlags, this.signatureIndex, byteVector7); + AnnotationWriter.putAnnotations( + this.symbolTable, + this.annotationWriter5, + this.annotationWriter4, + this.annotationWriter3, + this.annotationWriter2, + byteVector7); + if (this.annotationWriters != null) { + int value21 = this.symbolTable.addConstantUtf8("RuntimeVisibleParameterAnnotations"); + int value22; + ByteVector byteVector8; + if (this.count4 == 0) { + value22 = this.annotationWriters.length; + byteVector8 = byteVector7; + } else { + value22 = this.count4; + byteVector8 = byteVector7; + } + AnnotationWriter.putParameterAnnotations( + value21, this.annotationWriters, value22, byteVector8); + } + if (this.annotationWriters2 != null) { + int value23 = this.symbolTable.addConstantUtf8("RuntimeInvisibleParameterAnnotations"); + int value24; + ByteVector byteVector9; + if (this.count10 == 0) { + value24 = this.annotationWriters2.length; + byteVector9 = byteVector7; + } else { + value24 = this.count10; + byteVector9 = byteVector7; + } + AnnotationWriter.putParameterAnnotations( + value23, this.annotationWriters2, value24, byteVector9); + } + if (this.byteVector != null) { + byteVector7 + .putShort(this.symbolTable.addConstantUtf8("AnnotationDefault")) + .putInt(this.byteVector.length) + .putByteArray(this.byteVector.data, 0, this.byteVector.length); + } + if (this.byteVector6 != null) { + byteVector7 + .putShort(this.symbolTable.addConstantUtf8("MethodParameters")) + .putInt(1 + this.byteVector6.length) + .putByte(this.count6) + .putByteArray(this.byteVector6.data, 0, this.byteVector6.length); + } + if (this.attribute != null) { + this.attribute.putAttributes(this.symbolTable, byteVector7); + } + } + } + + @Override + public AnnotationVisitor visitLocalVariableAnnotation( + int value, + TypePath typePath, + Label[] labels, + Label[] labels2, + int[] values, + String text, + boolean matches) { + ByteVector byteVector; + (byteVector = new ByteVector()).putByte(value >>> 24).putShort(labels.length); + int value2 = 0; + for (int value3 = value2; value3 < labels.length; value3 = value2) { + ByteVector byteVector2 = + byteVector + .putShort(labels[value2].bytecodeOffset) + .putShort(labels2[value2].bytecodeOffset - labels[value2].bytecodeOffset); + int value4 = value2; + value2++; + byteVector2.putShort(values[value4]); + } + TypePath.put(typePath, byteVector); + byteVector.putShort(this.symbolTable.addConstantUtf8(text)).putShort(0); + return matches + ? (this.annotationWriter = + new AnnotationWriter(this.symbolTable, true, byteVector, this.annotationWriter)) + : (this.annotationWriter6 = + new AnnotationWriter(this.symbolTable, true, byteVector, this.annotationWriter6)); + } + + @Override + public void visitCode() {} + + public void update4() { + if (this.counts2 != null) { + if (this.byteVector2 == null) { + this.byteVector2 = new ByteVector(); + } + this.update5(); + this.count7++; + } + this.counts2 = this.counts; + this.counts = null; + } + + @Override + public void visitTableSwitchInsn(int value, int value2, Label label, Label... label2) + throws ClassNotFoundException { + this.count8 = this.code.length; + this.code.putByte(170).putByteArray(null, 0, (4 - this.code.length % 4) % 4); + label.put(this.code, this.count8, true); + this.code.putInt(value).putInt(value2); + int value3 = ((Label[]) label2).length; + int value4; + for (int value5 = value4 = 0; value5 < value3; value5 = value4) { + Label label3 = ((Label[]) label2)[value4]; + ByteVector byteVector = this.code; + value4++; + label3.put(byteVector, this.count8, true); + } + this.visitSwitchInsn(label, label2); + } + + @Override + public void visitLdcInsn(Object result) throws ClassNotFoundException { + this.count8 = this.code.length; + Symbol symbol; + Symbol symbol2 = symbol = this.symbolTable.addConstant(result); + int value2 = symbol2.index; + char value3; + boolean matches = + symbol2.tag == 5 + || symbol.tag == 6 + || symbol.tag == 17 && ((value3 = symbol.value.charAt(0)) == 'J' || value3 == 'D'); + MethodWriter methodWriter; + if (matches) { + methodWriter = this; + this.code.put12(20, value2); + } else if (value2 >= 256) { + methodWriter = this; + this.code.put12(19, value2); + } else { + methodWriter = this; + this.code.put11(18, value2); + } + if (methodWriter.label != null) { + if (this.compute == 4 || this.compute == 3) { + this.label.frame.execute(18, 0, symbol, this.symbolTable); + return; + } + int value4; + if ((value4 = this.count9 + (matches ? 2 : 1)) > this.count14) { + this.count14 = value4; + } + this.count9 = value4; + } + } + + @Override + public void visitVarInsn(int value, int value2) throws ClassNotFoundException { + this.count8 = this.code.length; + MethodWriter methodWriter; + if (value2 < 4 && value != 169) { + int value4; + if (value < 54) { + value4 = 26 + (value - 21 << 2) + value2; + methodWriter = this; + } else { + value4 = 59 + (value - 54 << 2) + value2; + methodWriter = this; + } + methodWriter.code.putByte(value4); + methodWriter = this; + } else if (value2 >= 256) { + methodWriter = this; + this.code.putByte(196).put12(value, value2); + } else { + methodWriter = this; + this.code.put11(value, value2); + } + label65: + { + if (methodWriter.label != null) { + if (this.compute == 4 || this.compute == 3) { + methodWriter = this; + this.label.frame.execute(value, value2, null, null); + break label65; + } + if (value == 169) { + methodWriter = this; + this.label.value3 = (short) (this.label.value3 | 64); + this.label.value5 = (short) this.count9; + this.update3(); + break label65; + } + int value6; + if ((value6 = this.count9 + STACK_SIZE_DELTA[value]) > this.count14) { + this.count14 = value6; + } + this.count9 = value6; + } + methodWriter = this; + } + int value7; + if (methodWriter.compute != 0 + && (value != 22 && value != 24 && value != 55 && value != 57 + ? (value7 = value2 + 1) + : (value7 = value2 + 2)) + > this.maxLocals) { + this.maxLocals = value7; + } + if (value >= 54 && this.compute == 4 && this.handler2 != null) { + this.visitLabel(new Label()); + } + } + + public MethodWriter( + SymbolTable symbolTable2, + int value, + String name, + String descriptor, + String text3, + String[] texts, + int compute) { + super(589824); + this.code = new ByteVector(); + this.symbolTable = symbolTable2; + this.accessFlags = "".equals(name) ? value | 262144 : value; + this.nameIndex = symbolTable2.addConstantUtf8(name); + this.name = name; + this.descriptorIndex = symbolTable2.addConstantUtf8(descriptor); + this.descriptor = descriptor; + this.signatureIndex = text3 == null ? 0 : symbolTable2.addConstantUtf8(text3); + if (texts != null && texts.length > 0) { + this.numberOfExceptions = texts.length; + int value3 = 0; + this.exceptionIndexTable = new int[this.numberOfExceptions]; + for (int index2 = 0; value3 < this.numberOfExceptions; value3 = index2) { + int[] values = this.exceptionIndexTable; + int value4 = symbolTable2.getSymbol3(texts[index2]).index; + int value5 = index2; + index2++; + values[value5] = value4; + } + } else { + this.numberOfExceptions = 0; + this.exceptionIndexTable = null; + } + this.compute = compute; + if (compute != 0) { + int value6 = Type.getArgumentsAndReturnSizes(descriptor) >> 2; + if ((value & 8) != 0) { + value6--; + } + this.maxLocals = value6; + this.currentLocals = value6; + this.firstBasicBlock = new Label(); + this.visitLabel(this.firstBasicBlock); + } + } + + @Override + public AnnotationVisitor visitAnnotationDefault() { + this.byteVector = new ByteVector(); + return new AnnotationWriter(this.symbolTable, false, this.byteVector, null); + } + + @Override + public void visitIntInsn(int value, int value2) throws ClassNotFoundException { + this.count8 = this.code.length; + MethodWriter methodWriter; + if (value == 17) { + methodWriter = this; + this.code.put12(value, value2); + } else { + methodWriter = this; + this.code.put11(value, value2); + } + if (methodWriter.label != null) { + if (this.compute == 4 || this.compute == 3) { + this.label.frame.execute(value, value2, null, null); + return; + } + if (value != 188) { + int value3; + if ((value3 = this.count9 + 1) > this.count14) { + this.count14 = value3; + } + this.count9 = value3; + } + } + } + + public void update5() { + int value = this.counts[1]; + int value2 = this.counts[2]; + if (this.symbolTable.getCount() < 50) { + this.byteVector2.putShort(this.counts[0]).putShort(value); + this.processCount5(3, 3 + value); + this.byteVector2.putShort(value2); + this.processCount5(3 + value, 3 + value + value2); + } else { + short value3; + int value4; + int value5; + int value6; + short value7; + label66: + { + value4 = this.count7 == 0 ? this.counts[0] : this.counts[0] - this.counts2[0] - 1; + value6 = this.counts2[1]; + value5 = value - value6; + value3 = 255; + if (value2 == 0) { + switch (value5) { + case -3: + case -2: + case -1: + value7 = value3 = 248; + break label66; + case 0: + value3 = (short) (value4 < 64 ? 0 : 251); + value7 = value3; + break label66; + case 1: + case 2: + case 3: + value7 = value3 = 252; + break label66; + } + } else if (value5 == 0 && value2 == 1) { + value3 = (short) (value4 < 63 ? 64 : 247); + } + value7 = value3; + } + label60: + { + if (value7 != 255) { + int value8 = 3; + int value9; + for (int value10 = value9 = 0; value10 < value6 && value9 < value; value10 = ++value9) { + if (this.counts[value8] != this.counts2[value8]) { + value7 = 255; + break label60; + } + value8++; + } + } + value7 = value3; + } + switch (value7) { + case 0: + this.byteVector2.putByte(value4); + return; + case 64: + this.byteVector2.putByte(64 + value4); + this.processCount5(3 + value, 4 + value); + return; + case 247: + this.byteVector2.putByte(247).putShort(value4); + this.processCount5(3 + value, 4 + value); + return; + case 248: + this.byteVector2.putByte(251 + value5).putShort(value4); + return; + case 251: + this.byteVector2.putByte(251).putShort(value4); + return; + case 252: + this.byteVector2.putByte(251 + value5).putShort(value4); + this.processCount5(3 + value6, 3 + value); + return; + case 255: + default: + this.byteVector2.putByte(255).putShort(value4).putShort(value); + this.processCount5(3, 3 + value); + this.byteVector2.putShort(value2); + this.processCount5(3 + value, 3 + value + value2); + } + } + } + + public void computeAllFrames() throws ClassNotFoundException { + Handler handler; + for (Handler handler3 = handler = this.handler2; + handler3 != null; + handler3 = handler = handler.nextHandler) { + String text = + handler.catchTypeDescriptor == null ? "java/lang/Throwable" : handler.catchTypeDescriptor; + int abstractTypeFromInternalName = + Frame.getAbstractTypeFromInternalName(this.symbolTable, text); + Label label3; + Label label4 = label3 = handler.handlerPc.getCanonicalInstance(); + label4.value3 = (short) (label4.value3 | 2); + Label canonicalInstance = handler.startPc.getCanonicalInstance(); + Label canonicalInstance2 = handler.endPc.getCanonicalInstance(); + for (Label label5 = canonicalInstance; + label5 != canonicalInstance2; + label5 = canonicalInstance = canonicalInstance.label2) { + canonicalInstance.outgoingEdges = + new Edge(abstractTypeFromInternalName, label3, canonicalInstance.outgoingEdges); + } + } + Frame frame2 = this.firstBasicBlock.frame; + frame2.setInputFrameFromDescriptor( + this.symbolTable, this.accessFlags, this.descriptor, this.maxLocals); + frame2.accept(this); + Label label6 = this.firstBasicBlock; + label6.label = Label.EMPTY_LIST; + int value = 0; + while (label6 != Label.EMPTY_LIST) { + Label label7 = label6; + label6 = label6.label; + label7.label = null; + label7.value3 = (short) (label7.value3 | 8); + int value2; + if ((value2 = label7.frame.getCounts5() + label7.value4) > value) { + value = value2; + } + Edge edge; + for (Edge edge2 = edge = label7.outgoingEdges; edge2 != null; edge2 = edge = edge.nextEdge) { + Label canonicalInstance3 = edge.successor.getCanonicalInstance(); + if (label7.frame.merge(this.symbolTable, canonicalInstance3.frame, edge.info) + && canonicalInstance3.label == null) { + canonicalInstance3.label = label6; + label6 = canonicalInstance3; + } + } + } + Label label8; + for (Label label9 = label8 = this.firstBasicBlock; + label9 != null; + label9 = label8 = label8.label2) { + if ((label8.value3 & 10) == 10) { + label8.frame.accept(this); + } + if ((label8.value3 & 8) == 0) { + Label label10 = label8.label2; + int value5 = label8.bytecodeOffset; + int value6; + if ((value6 = (label10 == null ? this.code.length : label10.bytecodeOffset) - 1) + >= value5) { + int value7; + for (int value8 = value7 = value5; value8 < value6; value8 = value7) { + byte value9 = 0; + int value10 = value7; + byte[] values = this.code.data; + value7++; + values[value10] = value9; + } + this.code.data[value6] = -65; + int value11 = this.visitFrameStart(value5, 0, 1); + this.counts[value11] = + Frame.getAbstractTypeFromInternalName(this.symbolTable, "java/lang/Throwable"); + this.update4(); + this.handler2 = Handler.removeRange(this.handler2, label8, label10); + value = Math.max(value, 1); + } + } + } + this.count = value; + } + + public void processValue(Object result) { + if (result instanceof Integer) { + this.byteVector2.putByte((Integer) result); + } else if (result instanceof String) { + this.byteVector2.putByte(7).putShort(this.symbolTable.getSymbol3((String) result).index); + } else { + this.byteVector2.putByte(8); + ((Label) result).put(this.byteVector2); + } + } + + @Override + public void visitFieldInsn(int value, String text, String text2, String text3) + throws ClassNotFoundException { + this.count8 = this.code.length; + Symbol symbol = this.symbolTable.addConstantFieldref(text, text2, text3); + this.code.put12(value, symbol.index); + if (this.label != null) { + if (this.compute == 4 || this.compute == 3) { + this.label.frame.execute(value, 0, symbol, this.symbolTable); + return; + } + int value2; + int value3; + label74: + { + char value4 = text3.charAt(0); + switch (value) { + case 178: + value3 = value2 = this.count9 + (value4 != 'D' && value4 != 'J' ? 1 : 2); + break label74; + case 179: + value3 = value2 = this.count9 + (value4 != 'D' && value4 != 'J' ? -1 : -2); + break label74; + case 180: + value3 = value2 = this.count9 + (value4 != 'D' && value4 != 'J' ? 0 : 1); + break label74; + case 181: + } + value3 = value2 = this.count9 + (value4 != 'D' && value4 != 'J' ? -2 : -3); + } + if (value3 > this.count14) { + this.count14 = value2; + } + this.count9 = value2; + } + } + + public int computeMethodInfoSize() { + if (this.count2 != 0) { + return 6 + this.count5; + } + int value = 8; + if (this.code.length > 0) { + if (this.code.length > 65535) { + throw new MethodTooLargeException( + this.symbolTable.getClassName(), this.name, this.descriptor, this.code.length); + } + this.symbolTable.addConstantUtf8("Code"); + value += 16 + this.code.length + Handler.calculateCount2(this.handler2); + if (this.byteVector2 != null) { + int value2 = this.symbolTable.getCount() >= 50 ? 1 : 0; + this.symbolTable.addConstantUtf8(value2 != 0 ? "StackMapTable" : "StackMap"); + value += 8 + this.byteVector2.length; + } + if (this.byteVector4 != null) { + this.symbolTable.addConstantUtf8("LineNumberTable"); + value += 8 + this.byteVector4.length; + } + if (this.byteVector5 != null) { + this.symbolTable.addConstantUtf8("LocalVariableTable"); + value += 8 + this.byteVector5.length; + } + if (this.byteVector3 != null) { + this.symbolTable.addConstantUtf8("LocalVariableTypeTable"); + value += 8 + this.byteVector3.length; + } + if (this.annotationWriter != null) { + value += this.annotationWriter.computeAnnotationsSize("RuntimeVisibleTypeAnnotations"); + } + if (this.annotationWriter6 != null) { + value += this.annotationWriter6.computeAnnotationsSize("RuntimeInvisibleTypeAnnotations"); + } + if (this.attribute2 != null) { + value += + this.attribute2.computeAttributesSize( + this.symbolTable, this.code.data, this.code.length, this.count, this.maxLocals); + } + } + if (this.numberOfExceptions > 0) { + this.symbolTable.addConstantUtf8("Exceptions"); + value += 8 + 2 * this.numberOfExceptions; + } + int value3 = + value + + Attribute.computeAttributesSize( + this.symbolTable, this.accessFlags, this.signatureIndex) + + AnnotationWriter.computeAnnotationsSize( + this.annotationWriter5, + this.annotationWriter4, + this.annotationWriter3, + this.annotationWriter2); + if (this.annotationWriters != null) { + value3 += + AnnotationWriter.computeParameterAnnotationsSize( + "RuntimeVisibleParameterAnnotations", + this.annotationWriters, + this.count4 == 0 ? this.annotationWriters.length : this.count4); + } + if (this.annotationWriters2 != null) { + value3 += + AnnotationWriter.computeParameterAnnotationsSize( + "RuntimeInvisibleParameterAnnotations", + this.annotationWriters2, + this.count10 == 0 ? this.annotationWriters2.length : this.count10); + } + if (this.byteVector != null) { + this.symbolTable.addConstantUtf8("AnnotationDefault"); + value3 += 6 + this.byteVector.length; + } + if (this.byteVector6 != null) { + this.symbolTable.addConstantUtf8("MethodParameters"); + value3 += 7 + this.byteVector6.length; + } + if (this.attribute != null) { + value3 += this.attribute.computeAttributesSize(this.symbolTable); + } + return value3; + } + + @Override + public AnnotationVisitor createAnnotationVisitor2( + int value, TypePath typePath, String text, boolean matches) { + return matches + ? (this.annotationWriter3 = + AnnotationWriter.create( + this.symbolTable, value, typePath, text, this.annotationWriter3)) + : (this.annotationWriter2 = + AnnotationWriter.create( + this.symbolTable, value, typePath, text, this.annotationWriter2)); + } + + public void processLabel3(int value, Label label2) { + this.label.outgoingEdges = new Edge(value, label2, this.label.outgoingEdges); + } + + public boolean isEnabled2() { + return this.enabled2; + } + + public final void collectAttributePrototypes(Attribute$Set attribute$Set) { + attribute$Set.addAttributes(this.attribute); + attribute$Set.addAttributes(this.attribute2); + } + + @Override + public void visitLookupSwitchInsn(Label label, int[] values, Label[] labels) + throws ClassNotFoundException { + this.count8 = this.code.length; + this.code.putByte(171).putByteArray(null, 0, (4 - this.code.length % 4) % 4); + label.put(this.code, this.count8, true); + this.code.putInt(labels.length); + int value = 0; + for (int value2 = value; value2 < labels.length; value2 = value) { + this.code.putInt(values[value]); + Label label2 = labels[value]; + ByteVector byteVector = this.code; + value++; + label2.put(byteVector, this.count8, true); + } + this.visitSwitchInsn(label, labels); + } + + @Override + public AnnotationVisitor createAnnotationVisitor( + int value, TypePath typePath, String text, boolean matches) { + return matches + ? (this.annotationWriter = + AnnotationWriter.create(this.symbolTable, value, typePath, text, this.annotationWriter)) + : (this.annotationWriter6 = + AnnotationWriter.create( + this.symbolTable, value, typePath, text, this.annotationWriter6)); + } + + @Override + public AnnotationVisitor visitAnnotation(String text, boolean matches) { + return matches + ? (this.annotationWriter5 = + AnnotationWriter.create(this.symbolTable, text, this.annotationWriter5)) + : (this.annotationWriter4 = + AnnotationWriter.create(this.symbolTable, text, this.annotationWriter4)); + } + + @Override + public void visitInvokeDynamicInsn(String text, String text2, Handle handle, Object... result) + throws ClassNotFoundException { + this.count8 = this.code.length; + Symbol symbol = this.symbolTable.addConstantInvokeDynamic(text, text2, handle, result); + this.code.put12(186, symbol.index); + this.code.putShort(0); + if (this.label != null) { + if (this.compute == 4 || this.compute == 3) { + this.label.frame.execute(186, 0, symbol, this.symbolTable); + return; + } + int value; + int value2 = ((value = symbol.getArgumentsAndReturnSizes()) & 3) - (value >> 2) + 1; + int value3; + if ((value3 = this.count9 + value2) > this.count14) { + this.count14 = value3; + } + this.count9 = value3; + } + } + + @Override + public AnnotationVisitor visitParameterAnnotation(int value, String text, boolean matches) { + if (matches) { + if (this.annotationWriters == null) { + this.annotationWriters = new AnnotationWriter[Type.getArgumentCount(this.descriptor)]; + } + return this.annotationWriters[value] = + AnnotationWriter.create(this.symbolTable, text, this.annotationWriters[value]); + } else { + if (this.annotationWriters2 == null) { + this.annotationWriters2 = new AnnotationWriter[Type.getArgumentCount(this.descriptor)]; + } + return this.annotationWriters2[value] = + AnnotationWriter.create(this.symbolTable, text, this.annotationWriters2[value]); + } + } + + @Override + public void visitMultiANewArrayInsn(String text, int value) throws ClassNotFoundException { + this.count8 = this.code.length; + Symbol symbol3 = this.symbolTable.getSymbol3(text); + this.code.put12(197, symbol3.index).putByte(value); + if (this.label != null) { + if (this.compute == 4 || this.compute == 3) { + this.label.frame.execute(197, value, symbol3, this.symbolTable); + return; + } + this.count9 += 1 - value; + } + } + + public void processCount7(int value, int value2) { + this.count2 = value + 6; + this.count5 = value2 - 6; + } +} diff --git a/src/main/java/com/allatori/lib/asm/ModuleVisitor.java b/src/main/java/com/allatori/lib/asm/ModuleVisitor.java new file mode 100644 index 0000000..a5a6bb0 --- /dev/null +++ b/src/main/java/com/allatori/lib/asm/ModuleVisitor.java @@ -0,0 +1,86 @@ +package com.allatori.lib.asm; + +public abstract class ModuleVisitor { + + public ModuleVisitor mv; + + public final int api; + + public ModuleVisitor(int api, ModuleVisitor moduleVisitor) { + super(); + if (api != 589824 + && api != 524288 + && api != 458752 + && api != 393216 + && api != 327680 + && api != 262144 + && api != 17432576) { + throw new IllegalArgumentException(stringConcat$0(api)); + } + if (api == 17432576) { + Constants.checkAsmExperimental(this); + } + this.api = api; + this.mv = moduleVisitor; + } + + public ModuleVisitor(int value) { + this(value, null); + } + + public void visitEnd() { + if (this.mv != null) { + this.mv.visitEnd(); + } + } + + public void processText(String text) { + if (this.mv != null) { + this.mv.processText(text); + } + } + + public void processText2(String text) { + if (this.mv != null) { + this.mv.processText2(text); + } + } + + public void processTexts(String text, int value, String... text2) { + if (this.mv != null) { + this.mv.processTexts(text, value, (String[]) text2); + } + } + + public void processText3(String text) { + if (this.mv != null) { + this.mv.processText3(text); + } + } + + public static String stringConcat$0(int value) { + return "Unsupported api " + value; + } + + public ModuleVisitor getDelegate() { + return this.mv; + } + + public void visitRequire(String text, int value, String text2) { + if (this.mv != null) { + this.mv.visitRequire(text, value, text2); + } + } + + public void visitProvide(String text, String... text2) { + if (this.mv != null) { + this.mv.visitProvide(text, (String[]) text2); + } + } + + public void processTexts2(String text, int value, String... text2) { + if (this.mv != null) { + this.mv.processTexts2(text, value, (String[]) text2); + } + } +} diff --git a/src/main/java/com/allatori/lib/asm/ModuleWriter.java b/src/main/java/com/allatori/lib/asm/ModuleWriter.java new file mode 100644 index 0000000..10d7727 --- /dev/null +++ b/src/main/java/com/allatori/lib/asm/ModuleWriter.java @@ -0,0 +1,211 @@ +package com.allatori.lib.asm; + +public final class ModuleWriter extends ModuleVisitor { + + public final ByteVector opens; + + public int count; + + public int count2; + + public int count3; + + public int count4; + + public final int moduleFlags; + + public final int moduleNameIndex; + + public final ByteVector provides; + + public final ByteVector exports; + + public final ByteVector packageIndex; + + public final int moduleVersionIndex; + + public int count5; + + public final ByteVector usesIndex; + + public int count6; + + public final SymbolTable symbolTable; + + public final ByteVector requires; + + public int count7; + + @Override + public void visitRequire(String text, int value, String text2) { + this.requires + .putShort(this.symbolTable.getSymbol4(text).index) + .putShort(value) + .putShort(text2 == null ? 0 : this.symbolTable.addConstantUtf8(text2)); + this.count2++; + } + + public ModuleWriter( + SymbolTable symbolTable2, int moduleNameIndex, int moduleFlags, int moduleVersionIndex) { + super(589824); + this.symbolTable = symbolTable2; + this.moduleNameIndex = moduleNameIndex; + this.moduleFlags = moduleFlags; + this.moduleVersionIndex = moduleVersionIndex; + this.requires = new ByteVector(); + this.exports = new ByteVector(); + this.opens = new ByteVector(); + this.usesIndex = new ByteVector(); + this.provides = new ByteVector(); + this.packageIndex = new ByteVector(); + } + + @Override + public void processTexts2(String text, int value, String... text2) { + this.opens.putShort(this.symbolTable.getSymbol2(text).index).putShort(value); + ModuleWriter moduleWriter; + if (((String[]) text2) == null) { + moduleWriter = this; + this.opens.putShort(0); + } else { + this.opens.putShort(((String[]) text2).length); + String[] texts = (String[]) text2; + int value2 = texts.length; + int value3; + for (int value4 = value3 = 0; value4 < value2; value4 = value3) { + String text3 = texts[value3]; + SymbolTable symbolTable2 = this.symbolTable; + ByteVector byteVector = this.opens; + value3++; + byteVector.putShort(symbolTable2.getSymbol4(text3).index); + } + moduleWriter = this; + } + moduleWriter.count7++; + } + + public int computeAttributesSize() { + this.symbolTable.addConstantUtf8("Module"); + int value = + 22 + + this.requires.length + + this.exports.length + + this.opens.length + + this.usesIndex.length + + this.provides.length; + if (this.count > 0) { + this.symbolTable.addConstantUtf8("ModulePackages"); + value += 8 + this.packageIndex.length; + } + if (this.count3 > 0) { + SymbolTable symbolTable2 = this.symbolTable; + value += 8; + symbolTable2.addConstantUtf8("ModuleMainClass"); + } + return value; + } + + @Override + public void processText3(String text) { + this.packageIndex.putShort(this.symbolTable.getSymbol2(text).index); + this.count++; + } + + @Override + public void processText(String text) { + this.count3 = this.symbolTable.getSymbol3(text).index; + } + + @Override + public void processTexts(String text, int value, String... text2) { + this.exports.putShort(this.symbolTable.getSymbol2(text).index).putShort(value); + ModuleWriter moduleWriter; + if (((String[]) text2) == null) { + moduleWriter = this; + this.exports.putShort(0); + } else { + this.exports.putShort(((String[]) text2).length); + String[] texts = (String[]) text2; + int value2 = texts.length; + int value3; + for (int value4 = value3 = 0; value4 < value2; value4 = value3) { + String text3 = texts[value3]; + SymbolTable symbolTable2 = this.symbolTable; + ByteVector byteVector = this.exports; + value3++; + byteVector.putShort(symbolTable2.getSymbol4(text3).index); + } + moduleWriter = this; + } + moduleWriter.count5++; + } + + @Override + public void visitProvide(String text, String... text2) { + this.provides.putShort(this.symbolTable.getSymbol3(text).index); + this.provides.putShort(((String[]) text2).length); + String[] texts = (String[]) text2; + int value = texts.length; + int value2; + for (int value3 = value2 = 0; value3 < value; value3 = value2) { + String text3 = texts[value2]; + SymbolTable symbolTable2 = this.symbolTable; + ByteVector byteVector = this.provides; + value2++; + byteVector.putShort(symbolTable2.getSymbol3(text3).index); + } + this.count4++; + } + + @Override + public void visitEnd() {} + + public void putAttributes(ByteVector byteVector) { + int value = + 16 + + this.requires.length + + this.exports.length + + this.opens.length + + this.usesIndex.length + + this.provides.length; + byteVector + .putShort(this.symbolTable.addConstantUtf8("Module")) + .putInt(value) + .putShort(this.moduleNameIndex) + .putShort(this.moduleFlags) + .putShort(this.moduleVersionIndex) + .putShort(this.count2) + .putByteArray(this.requires.data, 0, this.requires.length) + .putShort(this.count5) + .putByteArray(this.exports.data, 0, this.exports.length) + .putShort(this.count7) + .putByteArray(this.opens.data, 0, this.opens.length) + .putShort(this.count6) + .putByteArray(this.usesIndex.data, 0, this.usesIndex.length) + .putShort(this.count4) + .putByteArray(this.provides.data, 0, this.provides.length); + if (this.count > 0) { + byteVector + .putShort(this.symbolTable.addConstantUtf8("ModulePackages")) + .putInt(2 + this.packageIndex.length) + .putShort(this.count) + .putByteArray(this.packageIndex.data, 0, this.packageIndex.length); + } + if (this.count3 > 0) { + byteVector + .putShort(this.symbolTable.addConstantUtf8("ModuleMainClass")) + .putInt(2) + .putShort(this.count3); + } + } + + @Override + public void processText2(String text) { + this.usesIndex.putShort(this.symbolTable.getSymbol3(text).index); + this.count6++; + } + + public int getAttributeCount() { + return 1 + (this.count > 0 ? 1 : 0) + (this.count3 > 0 ? 1 : 0); + } +} diff --git a/src/main/java/com/allatori/lib/asm/Opcodes.java b/src/main/java/com/allatori/lib/asm/Opcodes.java new file mode 100644 index 0000000..8e27cf7 --- /dev/null +++ b/src/main/java/com/allatori/lib/asm/Opcodes.java @@ -0,0 +1,502 @@ +package com.allatori.lib.asm; + +public interface Opcodes { + + int COUNT = 32768; + + int ASM6 = 393216; + + int COUNT2 = 50; + + int JSR = 168; + + int FSUB = 102; + + int L2D = 138; + + int COUNT3 = 128; + + int COUNT4 = 6; + + int IFGT = 157; + + int COUNT5 = 32; + + int LSHL = 121; + + int COUNT6 = 55; + + int COUNT7 = 57; + + int V16 = 60; + + Integer INTEGER3 = 0; + + Integer INTEGER4 = 1; + + Integer INTEGER6 = 2; + + Integer INTEGER = 3; + + Integer INTEGER5 = 4; + + Integer INTEGER2 = 5; + + Integer INTEGER7 = 6; + + int ASM9 = 589824; + + int DUP2_X1 = 93; + + int DUP2 = 92; + + @Deprecated int ASM10_EXPERIMENTAL = 17432576; + + int COUNT8 = 128; + + int ACC_RECORD = 65536; + + int IRETURN = 172; + + int COUNT9 = 4; + + int COUNT10 = 10; + + int COUNT11 = 64; + + int COUNT12 = 46; + + int IXOR = 130; + + int COUNT13 = 6; + + int COUNT14 = 2; + + int V_PREVIEW = -65536; + + int COUNT15 = 64; + + int COUNT16 = 32; + + int LCMP = 148; + + int IASTORE = 79; + + int LOOKUPSWITCH = 171; + + int COUNT17 = 54; + + int NEWARRAY = 188; + + int COUNT18 = 9; + + int RET = 169; + + int ACC_ANNOTATION = 8192; + + int ASM8 = 524288; + + int V19 = 63; + + int INVOKEVIRTUAL = 182; + + int LDC = 18; + + int IINC = 132; + + int IFGE = 156; + + int COUNT19 = 128; + + int COUNT20 = 9; + + int DCMPG = 152; + + int DLOAD = 24; + + int CASTORE = 85; + + int DDIV = 111; + + int V21 = 65; + + int COUNT21 = 51; + + int POP2 = 88; + + int INVOKESPECIAL = 183; + + int FRETURN = 174; + + int COUNT22 = 4; + + int D2F = 144; + + int COUNT23 = 8; + + int ILOAD = 21; + + int LAND = 127; + + int V15 = 59; + + int PUTFIELD = 181; + + int POP = 87; + + int AASTORE = 83; + + int LLOAD = 22; + + int COUNT24 = 9; + + int FNEG = 118; + + int COUNT25 = 5; + + int INVOKEINTERFACE = 185; + + int DUP_X1 = 90; + + int DCONST_1 = 15; + + int ACC_ABSTRACT = 1024; + + int ACC_INTERFACE = 512; + + int COUNT26 = 16; + + int COUNT27 = 51; + + int LUSHR = 125; + + int GETFIELD = 180; + + int PUTSTATIC = 179; + + int V24 = 68; + + int COUNT28 = 11; + + int LREM = 113; + + int IDIV = 108; + + int ARRAYLENGTH = 190; + + int COUNT29 = 52; + + int IF_ICMPGT = 163; + + int F2I = 139; + + int LDIV = 109; + + int SIPUSH = 17; + + int COUNT30 = 4; + + int COUNT31 = 6; + + int I2D = 135; + + int ARETURN = 176; + + int IF_ACMPNE = 166; + + int ASM5 = 327680; + + int COUNT32 = 2; + + int COUNT33 = 47; + + int V17 = 61; + + int COUNT34 = 1; + + int COUNT35 = 4; + + int COUNT36 = 55; + + int IF_ICMPNE = 160; + + int MONITOREXIT = 195; + + int I2B = 145; + + int COUNT37 = 64; + + int L2F = 137; + + int FASTORE = 81; + + int COUNT38 = 2; + + int COUNT39 = 53; + + int IF_ICMPEQ = 159; + + int COUNT40 = 3; + + int RETURN = 177; + + int DCONST_0 = 14; + + int SASTORE = 86; + + int COUNT41 = 52; + + int COUNT42 = 1; + + int IF_ICMPGE = 162; + + int COUNT43 = 64; + + int MULTIANEWARRAY = 197; + + int DSUB = 103; + + int GETSTATIC = 178; + + int COUNT44 = 1; + + int IFEQ = 153; + + int ACC_ENUM = 16384; + + int NEW = 187; + + int COUNT45 = 58; + + int LASTORE = 80; + + int ISHL = 120; + + int COUNT46 = 11; + + int FMUL = 106; + + int COUNT47 = 32; + + int ASM4 = 262144; + + int FCONST_2 = 13; + + int COUNT48 = 49; + + int LOR = 129; + + int LSHR = 123; + + int COUNT49 = 53; + + int FCONST_1 = 12; + + int IF_ICMPLE = 164; + + int LADD = 97; + + int D2I = 142; + + int ANEWARRAY = 189; + + int ASM7 = 458752; + + int COUNT50 = 0; + + int COUNT51 = 7; + + int COUNT52 = 48; + + int ATHROW = 191; + + int I2S = 147; + + int COUNT53 = 0; + + int LSUB = 101; + + int FCMPL = 149; + + int COUNT54 = 50; + + int IF_ICMPLT = 161; + + int I2C = 146; + + int V1_1 = 196653; + + int IFNULL = 198; + + int DCMPL = 151; + + int DADD = 99; + + int LNEG = 117; + + int DUP_X2 = 91; + + int FLOAD = 23; + + int ACC_STRICT = 2048; + + int DUP2_X2 = 94; + + int V22 = 66; + + int FDIV = 110; + + int LXOR = 131; + + int DUP = 89; + + int INVOKESTATIC = 184; + + int COUNT55 = 5; + + int COUNT56 = 54; + + int FADD = 98; + + int COUNT57 = 1; + + int DMUL = 107; + + int IF_ACMPEQ = 165; + + int ACC_SYNTHETIC = 4096; + + int L2I = 136; + + int COUNT58 = 7; + + int SWAP = 95; + + int COUNT59 = 256; + + int COUNT60 = 57; + + int ISHR = 122; + + int DREM = 115; + + int COUNT61 = 56; + + int BASTORE = 84; + + int DRETURN = 175; + + int COUNT62 = 56; + + int ALOAD = 25; + + int COUNT63 = 10; + + int LMUL = 105; + + int FREM = 114; + + int COUNT64 = 8; + + int COUNT65 = 8; + + int COUNT66 = 3; + + int F2D = 141; + + int COUNT67 = 256; + + int FCMPG = 150; + + int F2L = 140; + + int COUNT68 = 70; + + int IADD = 96; + + int COUNT69 = 58; + + int COUNT70 = 48; + + int COUNT71 = 3; + + int COUNT72 = 47; + + int GOTO = 167; + + int ISUB = 100; + + int COUNT73 = 4; + + int IMUL = 104; + + int TABLESWITCH = 170; + + int IFLE = 158; + + int DNEG = 119; + + int V25 = 69; + + int MONITORENTER = 194; + + int INVOKEDYNAMIC = 186; + + int V18 = 62; + + int IFNE = 154; + + int COUNT74 = 49; + + int CHECKCAST = 192; + + int INEG = 116; + + int F_NEW = -1; + + int COUNT75 = 46; + + int COUNT76 = 32768; + + int ACC_DEPRECATED = 131072; + + int IFNONNULL = 199; + + int D2L = 143; + + int COUNT77 = 2; + + int DASTORE = 82; + + int COUNT78 = 7; + + int COUNT79 = 5; + + int LRETURN = 173; + + int IREM = 112; + + int IFLT = 155; + + int IUSHR = 124; + + int COUNT80 = 71; + + int I2F = 134; + + int IAND = 126; + + int COUNT81 = 32; + + int COUNT82 = 256; + + int V23 = 67; + + int COUNT83 = 16; + + int COUNT84 = 8; + + int INSTANCEOF = 193; + + int I2L = 133; +} diff --git a/src/main/java/com/allatori/lib/asm/RecordComponentVisitor.java b/src/main/java/com/allatori/lib/asm/RecordComponentVisitor.java new file mode 100644 index 0000000..c3d4d21 --- /dev/null +++ b/src/main/java/com/allatori/lib/asm/RecordComponentVisitor.java @@ -0,0 +1,61 @@ +package com.allatori.lib.asm; + +public abstract class RecordComponentVisitor { + + public RecordComponentVisitor delegate; + + public final int api; + + public RecordComponentVisitor(int api, RecordComponentVisitor recordComponentVisitor) { + super(); + if (api != 589824 + && api != 524288 + && api != 458752 + && api != 393216 + && api != 327680 + && api != 262144 + && api != 17432576) { + throw new IllegalArgumentException(stringConcat$0(api)); + } + if (api == 17432576) { + Constants.checkAsmExperimental(this); + } + this.api = api; + this.delegate = recordComponentVisitor; + } + + public AnnotationVisitor visitAnnotation(String text, boolean matches) { + return this.delegate != null ? this.delegate.visitAnnotation(text, matches) : null; + } + + public static String stringConcat$0(int value) { + return "Unsupported api " + value; + } + + public RecordComponentVisitor(int value) { + this(value, null); + } + + public AnnotationVisitor visitTypeAnnotation( + int value, TypePath typePath, String text, boolean matches) { + return this.delegate != null + ? this.delegate.visitTypeAnnotation(value, typePath, text, matches) + : null; + } + + public RecordComponentVisitor getDelegate() { + return this.delegate; + } + + public void visitAttribute(Attribute attribute) { + if (this.delegate != null) { + this.delegate.visitAttribute(attribute); + } + } + + public void visitEnd() { + if (this.delegate != null) { + this.delegate.visitEnd(); + } + } +} diff --git a/src/main/java/com/allatori/lib/asm/RecordComponentWriter.java b/src/main/java/com/allatori/lib/asm/RecordComponentWriter.java new file mode 100644 index 0000000..782b4f1 --- /dev/null +++ b/src/main/java/com/allatori/lib/asm/RecordComponentWriter.java @@ -0,0 +1,115 @@ +package com.allatori.lib.asm; + +public final class RecordComponentWriter extends RecordComponentVisitor { + + public final int nameIndex; + + public int signatureIndex; + + public AnnotationWriter annotationWriter; + + public AnnotationWriter annotationWriter2; + + public AnnotationWriter annotationWriter3; + + public final SymbolTable symbolTable; + + public AnnotationWriter annotationWriter4; + + public Attribute firstAttribute; + + public final int descriptorIndex; + + public final void collectAttributePrototypes(Attribute$Set attribute$Set) { + attribute$Set.addAttributes(this.firstAttribute); + } + + @Override + public void visitEnd() {} + + public int computeRecordComponentInfoSize() { + int value = + 6 + + Attribute.computeAttributesSize(this.symbolTable, 0, this.signatureIndex) + + AnnotationWriter.computeAnnotationsSize( + this.annotationWriter4, + this.annotationWriter2, + this.annotationWriter, + this.annotationWriter3); + if (this.firstAttribute != null) { + value += this.firstAttribute.computeAttributesSize(this.symbolTable); + } + return value; + } + + @Override + public AnnotationVisitor visitAnnotation(String text, boolean matches) { + return matches + ? (this.annotationWriter4 = + AnnotationWriter.create(this.symbolTable, text, this.annotationWriter4)) + : (this.annotationWriter2 = + AnnotationWriter.create(this.symbolTable, text, this.annotationWriter2)); + } + + public void putRecordComponentInfo(ByteVector byteVector) { + byteVector.putShort(this.nameIndex).putShort(this.descriptorIndex); + int value = 0; + if (this.signatureIndex != 0) { + value++; + } + if (this.annotationWriter4 != null) { + value++; + } + if (this.annotationWriter2 != null) { + value++; + } + if (this.annotationWriter != null) { + value++; + } + if (this.annotationWriter3 != null) { + value++; + } + if (this.firstAttribute != null) { + value += this.firstAttribute.getAttributeCount(); + } + byteVector.putShort(value); + Attribute.putAttributes(this.symbolTable, 0, this.signatureIndex, byteVector); + AnnotationWriter.putAnnotations( + this.symbolTable, + this.annotationWriter4, + this.annotationWriter2, + this.annotationWriter, + this.annotationWriter3, + byteVector); + if (this.firstAttribute != null) { + this.firstAttribute.putAttributes(this.symbolTable, byteVector); + } + } + + @Override + public void visitAttribute(Attribute attribute) { + attribute.nextAttribute = this.firstAttribute; + this.firstAttribute = attribute; + } + + public RecordComponentWriter(SymbolTable symbolTable2, String text, String text2, String text3) { + super(589824); + this.symbolTable = symbolTable2; + this.nameIndex = symbolTable2.addConstantUtf8(text); + this.descriptorIndex = symbolTable2.addConstantUtf8(text2); + if (text3 != null) { + this.signatureIndex = symbolTable2.addConstantUtf8(text3); + } + } + + @Override + public AnnotationVisitor visitTypeAnnotation( + int value, TypePath typePath, String text, boolean matches) { + return matches + ? (this.annotationWriter = + AnnotationWriter.create(this.symbolTable, value, typePath, text, this.annotationWriter)) + : (this.annotationWriter3 = + AnnotationWriter.create( + this.symbolTable, value, typePath, text, this.annotationWriter3)); + } +} diff --git a/src/main/java/com/allatori/lib/asm/Symbol.java b/src/main/java/com/allatori/lib/asm/Symbol.java new file mode 100644 index 0000000..08d5b94 --- /dev/null +++ b/src/main/java/com/allatori/lib/asm/Symbol.java @@ -0,0 +1,79 @@ +package com.allatori.lib.asm; + +public abstract class Symbol { + + public static final int CONSTANT_NAME_AND_TYPE_TAG = 12; + + public static final int UNINITIALIZED_TYPE_TAG = 129; + + public final int tag; + + public final String value; + + public static final int TYPE_TAG = 128; + + public static final int MERGED_TYPE_TAG = 131; + + public static final int BOOTSTRAP_METHOD_TAG = 64; + + public static final int CONSTANT_INTERFACE_METHODREF_TAG = 11; + + public static final int CONSTANT_CLASS_TAG = 7; + + public final long data; + + public static final int CONSTANT_INTEGER_TAG = 3; + + public static final int CONSTANT_FLOAT_TAG = 4; + + public static final int CONSTANT_INVOKE_DYNAMIC_TAG = 18; + + public static final int CONSTANT_METHOD_TYPE_TAG = 16; + + public static final int CONSTANT_DYNAMIC_TAG = 17; + + public static final int CONSTANT_DOUBLE_TAG = 6; + + public static final int CONSTANT_METHOD_HANDLE_TAG = 15; + + public final String name; + + public static final int FORWARD_UNINITIALIZED_TYPE_TAG = 130; + + public static final int CONSTANT_LONG_TAG = 5; + + public static final int CONSTANT_STRING_TAG = 8; + + public static final int CONSTANT_PACKAGE_TAG = 20; + + public int count; + + public static final int CONSTANT_MODULE_TAG = 19; + + public static final int CONSTANT_UTF8_TAG = 1; + + public final String owner; + + public final int index; + + public static final int CONSTANT_FIELDREF_TAG = 9; + + public static final int CONSTANT_METHODREF_TAG = 10; + + public int getArgumentsAndReturnSizes() { + if (this.count == 0) { + this.count = Type.getArgumentsAndReturnSizes(this.value); + } + return this.count; + } + + public Symbol(int index, int tag, String owner, String name, String value, long data) { + super(); + this.index = index; + this.tag = tag; + this.owner = owner; + this.name = name; + this.value = value; + this.data = data; + } +} diff --git a/src/main/java/com/allatori/lib/asm/SymbolTable$Entry.java b/src/main/java/com/allatori/lib/asm/SymbolTable$Entry.java new file mode 100644 index 0000000..8e6b1c4 --- /dev/null +++ b/src/main/java/com/allatori/lib/asm/SymbolTable$Entry.java @@ -0,0 +1,34 @@ +package com.allatori.lib.asm; + +public final class SymbolTable$Entry extends Symbol { + + public SymbolTable$Entry next; + + public final int hashCode; + + public SymbolTable$Entry(int value, int value2, String text, long value3, int hashCode) { + super(value, value2, null, null, text, value3); + this.hashCode = hashCode; + } + + public SymbolTable$Entry(int value, int value2, long value3, int hashCode) { + super(value, value2, null, null, null, value3); + this.hashCode = hashCode; + } + + public SymbolTable$Entry(int value, int value2, String text, String text2, int hashCode) { + super(value, value2, null, text, text2, 0L); + this.hashCode = hashCode; + } + + public SymbolTable$Entry(int value, int value2, String text, int hashCode) { + super(value, value2, null, null, text, 0L); + this.hashCode = hashCode; + } + + public SymbolTable$Entry( + int value, int value2, String text, String text2, String text3, long value3, int hashCode) { + super(value, value2, text, text2, text3, value3); + this.hashCode = hashCode; + } +} diff --git a/src/main/java/com/allatori/lib/asm/SymbolTable$LabelEntry.java b/src/main/java/com/allatori/lib/asm/SymbolTable$LabelEntry.java new file mode 100644 index 0000000..8e9ab60 --- /dev/null +++ b/src/main/java/com/allatori/lib/asm/SymbolTable$LabelEntry.java @@ -0,0 +1,16 @@ +package com.allatori.lib.asm; + +public final class SymbolTable$LabelEntry { + + public final int index; + + public final Label label; + + public SymbolTable$LabelEntry next; + + public SymbolTable$LabelEntry(int index, Label label2) { + super(); + this.index = index; + this.label = label2; + } +} diff --git a/src/main/java/com/allatori/lib/asm/SymbolTable.java b/src/main/java/com/allatori/lib/asm/SymbolTable.java new file mode 100644 index 0000000..8655029 --- /dev/null +++ b/src/main/java/com/allatori/lib/asm/SymbolTable.java @@ -0,0 +1,865 @@ +package com.allatori.lib.asm; + +public final class SymbolTable { + + public int count; + + public int count2; + + public int constantPoolCount; + + public SymbolTable$Entry[] entries; + + public final ClassReader sourceClassReader; + + public ByteVector constantPool; + + public final ClassWriter classWriter; + + public SymbolTable$Entry[] entrys; + + public String className; + + public int count3; + + public SymbolTable$LabelEntry[] labelEntrys; + + public int count4; + + public ByteVector byteVector; + + public int count5; + + public SymbolTable$LabelEntry[] labelEntrys2; + + public int addConstantUtf8(String text) { + int value2 = hash(1, text); + SymbolTable$Entry symbolTable$Entry; + for (SymbolTable$Entry symbolTable$Entry2 = symbolTable$Entry = this.get(value2); + symbolTable$Entry2 != null; + symbolTable$Entry2 = symbolTable$Entry = symbolTable$Entry.next) { + if (symbolTable$Entry.tag == 1 + && symbolTable$Entry.hashCode == value2 + && symbolTable$Entry.value.equals(text)) { + return symbolTable$Entry.index; + } + } + this.constantPool.putByte(1).putUTF8(text); + return this.put(new SymbolTable$Entry(this.constantPoolCount++, 1, text, value2)).index; + } + + public SymbolTable(ClassWriter classWriter2, ClassReader classReader) { + super(); + this.classWriter = classWriter2; + this.sourceClassReader = classReader; + byte[] values = classReader.classFileBuffer; + int value = classReader.getItem(1) - 1; + int value2 = classReader.header - value; + this.constantPoolCount = classReader.getItemCount(); + this.constantPool = new ByteVector(value2); + this.constantPool.putByteArray(values, value, value2); + this.entries = new SymbolTable$Entry[this.constantPoolCount * 2]; + char[] values2 = new char[classReader.getMaxStringLength()]; + byte value3 = 0; + int value4; + int value5 = value4 = 1; + while (value5 < this.constantPoolCount) { + int value6; + byte value7; + switch (value7 = values[(value6 = classReader.getItem(value4)) - 1]) { + case 1: + this.addConstantUtf8(value4, classReader.getText4(value4, values2)); + value5 = value4; + break; + case 2: + case 13: + case 14: + default: + throw new IllegalArgumentException(); + case 3: + case 4: + this.addConstantIntegerOrFloat(value4, value7, classReader.readInt(value6)); + value5 = value4; + break; + case 5: + case 6: + this.addConstantLongOrDouble(value4, value7, classReader.readLong(value6)); + value5 = value4; + break; + case 7: + case 8: + case 16: + case 19: + case 20: + this.addConstantUtf8Reference(value4, value7, classReader.getText2(value6, values2)); + value5 = value4; + break; + case 9: + case 10: + case 11: + int item = classReader.getItem(classReader.readUnsignedShort(value6 + 2)); + value5 = value4; + this.addConstantMemberReference( + value4, + value7, + classReader.getText5(value6, values2), + classReader.getText2(item, values2), + classReader.getText2(item + 2, values2)); + break; + case 12: + this.addConstantNameAndType( + value4, + classReader.getText2(value6, values2), + classReader.getText2(value6 + 2, values2)); + value5 = value4; + break; + case 15: + int value8; + int item2 = + classReader.getItem( + classReader.readUnsignedShort( + (value8 = classReader.getItem(classReader.readUnsignedShort(value6 + 1))) + + 2)); + this.addConstantMethodHandle( + value4, + classReader.readByte(value6), + classReader.getText5(value8, values2), + classReader.getText2(item2, values2), + classReader.getText2(item2 + 2, values2), + classReader.readByte(value8 - 1) == 11); + value5 = value4; + break; + case 17: + case 18: + value3 = 1; + int item3 = classReader.getItem(classReader.readUnsignedShort(value6 + 2)); + this.addConstantDynamicOrInvokeDynamicReference( + value7, + value4, + classReader.getText2(item3, values2), + classReader.getText2(item3 + 2, values2), + classReader.readUnsignedShort(value6)); + value5 = value4; + } + value5 = value4 = value5 + (value7 != 5 && value7 != 6 ? 1 : 2); + } + if (value3 != 0) { + this.copyBootstrapMethods(classReader, values2); + } + } + + public int getConstantPoolCount() { + return this.constantPoolCount; + } + + public Symbol getSymbol(String text) { + return this.addConstantUtf8Reference(16, text); + } + + public Symbol getSymbol(int value) { + return this.addConstantIntegerOrFloat(3, value); + } + + public int addForwardUninitializedType(String text, Label label) { + int value2 = this.getOrAddLabelEntry(label).index; + int value3; + SymbolTable$Entry symbolTable$Entry; + for (SymbolTable$Entry symbolTable$Entry2 = + symbolTable$Entry = this.get(value3 = hash(130, text, value2)); + symbolTable$Entry2 != null; + symbolTable$Entry2 = symbolTable$Entry = symbolTable$Entry.next) { + if (symbolTable$Entry.tag == 130 + && symbolTable$Entry.hashCode == value3 + && symbolTable$Entry.data == value2 + && symbolTable$Entry.value.equals(text)) { + return symbolTable$Entry.index; + } + } + return this.addTypeInternal(new SymbolTable$Entry(this.count5, 130, text, value2, value3)); + } + + public void addConstantNameAndType(int value, String text, String text2) { + this.add(new SymbolTable$Entry(value, 12, text, text2, hash(12, text, text2))); + } + + public Symbol addConstantDynamicOrInvokeDynamicReference( + int value2, String text, String text2, int value3) { + int value4 = hash(value2, text, text2, value3); + SymbolTable$Entry symbolTable$Entry; + for (SymbolTable$Entry symbolTable$Entry2 = symbolTable$Entry = this.get(value4); + symbolTable$Entry2 != null; + symbolTable$Entry2 = symbolTable$Entry = symbolTable$Entry.next) { + if (symbolTable$Entry.tag == value2 + && symbolTable$Entry.hashCode == value4 + && symbolTable$Entry.data == value3 + && symbolTable$Entry.name.equals(text) + && symbolTable$Entry.value.equals(text2)) { + return symbolTable$Entry; + } + } + this.constantPool.put122(value2, value3, this.addConstantNameAndType(text, text2)); + return this.put( + new SymbolTable$Entry(this.constantPoolCount++, value2, null, text, text2, value3, value4)); + } + + public int addTypeInternal(SymbolTable$Entry symbolTable$Entry) { + if (this.entrys == null) { + this.entrys = new SymbolTable$Entry[16]; + } + if (this.count5 == this.entrys.length) { + SymbolTable$Entry[] symbolTable$Entrys = new SymbolTable$Entry[2 * this.entrys.length]; + System.arraycopy(this.entrys, 0, symbolTable$Entrys, 0, this.entrys.length); + this.entrys = symbolTable$Entrys; + } + this.entrys[this.count5++] = symbolTable$Entry; + return this.put(symbolTable$Entry).index; + } + + public Symbol addConstantMethodHandle( + int value2, String text, String text2, String text3, boolean matches) { + int constantMethodHandleSymbolData = getConstantMethodHandleSymbolData(value2, matches); + int value3 = hash(15, text, text2, text3, constantMethodHandleSymbolData); + SymbolTable$Entry symbolTable$Entry; + for (SymbolTable$Entry symbolTable$Entry2 = symbolTable$Entry = this.get(value3); + symbolTable$Entry2 != null; + symbolTable$Entry2 = symbolTable$Entry = symbolTable$Entry.next) { + if (symbolTable$Entry.tag == 15 + && symbolTable$Entry.hashCode == value3 + && symbolTable$Entry.data == constantMethodHandleSymbolData + && symbolTable$Entry.owner.equals(text) + && symbolTable$Entry.name.equals(text2) + && symbolTable$Entry.value.equals(text3)) { + return symbolTable$Entry; + } + } + SymbolTable symbolTable; + if (value2 <= 4) { + symbolTable = this; + this.constantPool.put112(15, value2, this.addConstantFieldref(text, text2, text3).index); + } else { + symbolTable = this; + this.constantPool.put112( + 15, value2, this.addConstantMethodref(text, text2, text3, matches).index); + } + return symbolTable.put( + new SymbolTable$Entry( + this.constantPoolCount++, + 15, + text, + text2, + text3, + constantMethodHandleSymbolData, + value3)); + } + + public static int getConstantMethodHandleSymbolData(int value, boolean matches) { + return value > 4 && matches ? value << 8 : value; + } + + public Symbol addConstantLongOrDouble(int value, long value2) { + int value3 = hash(value, value2); + SymbolTable$Entry symbolTable$Entry; + for (SymbolTable$Entry symbolTable$Entry2 = symbolTable$Entry = this.get(value3); + symbolTable$Entry2 != null; + symbolTable$Entry2 = symbolTable$Entry = symbolTable$Entry.next) { + if (symbolTable$Entry.tag == value + && symbolTable$Entry.hashCode == value3 + && symbolTable$Entry.data == value2) { + return symbolTable$Entry; + } + } + int value4 = this.constantPoolCount; + this.constantPool.putByte(value).putLong(value2); + this.constantPoolCount += 2; + return this.put(new SymbolTable$Entry(value4, value, value2, value3)); + } + + public void addConstantUtf8Reference(int value, int value2, String text) { + this.add(new SymbolTable$Entry(value, value2, text, hash(value2, text))); + } + + public Symbol addConstantUtf8Reference(int value2, String text) { + int value3 = hash(value2, text); + SymbolTable$Entry symbolTable$Entry; + for (SymbolTable$Entry symbolTable$Entry2 = symbolTable$Entry = this.get(value3); + symbolTable$Entry2 != null; + symbolTable$Entry2 = symbolTable$Entry = symbolTable$Entry.next) { + if (symbolTable$Entry.tag == value2 + && symbolTable$Entry.hashCode == value3 + && symbolTable$Entry.value.equals(text)) { + return symbolTable$Entry; + } + } + this.constantPool.put12(value2, this.addConstantUtf8(text)); + return this.put(new SymbolTable$Entry(this.constantPoolCount++, value2, text, value3)); + } + + public ClassReader getSource() { + return this.sourceClassReader; + } + + public Symbol addBootstrapMethod(Handle handle, Object... result) { + ByteVector byteVector2 = this.byteVector; + if (this.byteVector == null) { + byteVector2 = this.byteVector = new ByteVector(); + } + int value; + int[] values = new int[value = result.length]; + int value2; + for (int value3 = value2 = 0; value3 < value; value3 = value2) { + int value4 = this.addConstant(result[value2]).index; + int value5 = value2; + value2++; + values[value5] = value4; + } + int value6 = byteVector2.length; + byteVector2.putShort( + this.addConstantMethodHandle( + handle.getTag(), + handle.getOwner(), + handle.getName(), + handle.getDescriptor(), + handle.isInterface()) + .index); + byteVector2.putShort(value); + int value7 = 0; + for (int value8 = value7; value8 < value; value8 = value7) { + int value9 = value7; + ByteVector byteVector3 = byteVector2; + value7++; + byteVector3.putShort(values[value9]); + } + int value10 = byteVector2.length - value6; + int value11 = handle.hashCode(); + int value12 = result.length; + int value13; + for (int value14 = value13 = 0; value14 < value12; value14 = value13) { + Object result2 = ((Object[]) result)[value13]; + int value15 = value11; + value13++; + value11 = value15 ^ result2.hashCode(); + } + int value16 = value11 & 2147483647; + return this.addBootstrapMethod(value6, value10, value16); + } + + public void processByteVector(ByteVector byteVector) { + byteVector + .putShort(this.constantPoolCount) + .putByteArray(this.constantPool.data, 0, this.constantPool.length); + } + + public static int hash(int value, String text) { + return 2147483647 & value + text.hashCode(); + } + + public int addMergedType(int value2, int value3) throws ClassNotFoundException { + long value4 = value2 < value3 ? value2 | (long) value3 << 32 : value3 | (long) value2 << 32; + int value5 = hash(131, value2 + value3); + SymbolTable$Entry symbolTable$Entry; + for (SymbolTable$Entry symbolTable$Entry2 = symbolTable$Entry = this.get(value5); + symbolTable$Entry2 != null; + symbolTable$Entry2 = symbolTable$Entry = symbolTable$Entry.next) { + if (symbolTable$Entry.tag == 131 + && symbolTable$Entry.hashCode == value5 + && symbolTable$Entry.data == value4) { + return symbolTable$Entry.count; + } + } + String text = this.entrys[value2].value; + String text2 = this.entrys[value3].value; + int value6 = this.addType(this.classWriter.getCommonSuperClass(text, text2)); + this.put(new SymbolTable$Entry(this.count5, 131, value4, value5)).count = value6; + return value6; + } + + public Symbol getSymbol2(int value) { + return this.entrys[value]; + } + + public static int hash(int value, String text, String text2) { + return 2147483647 & value + text.hashCode() * text2.hashCode(); + } + + public SymbolTable(ClassWriter classWriter2) { + super(); + this.classWriter = classWriter2; + this.sourceClassReader = null; + this.entries = new SymbolTable$Entry[256]; + this.constantPoolCount = 1; + this.constantPool = new ByteVector(); + } + + public int addType(String text) { + int value2 = hash(128, text); + SymbolTable$Entry symbolTable$Entry; + for (SymbolTable$Entry symbolTable$Entry2 = symbolTable$Entry = this.get(value2); + symbolTable$Entry2 != null; + symbolTable$Entry2 = symbolTable$Entry = symbolTable$Entry.next) { + if (symbolTable$Entry.tag == 128 + && symbolTable$Entry.hashCode == value2 + && symbolTable$Entry.value.equals(text)) { + return symbolTable$Entry.index; + } + } + return this.addTypeInternal(new SymbolTable$Entry(this.count5, 128, text, value2)); + } + + public int setMajorVersionAndClassName(int count, String className) { + this.count = count; + this.className = className; + return this.getSymbol3(className).index; + } + + public Symbol addConstantIntegerOrFloat(int value, int value2) { + int value3 = hash(value, value2); + SymbolTable$Entry symbolTable$Entry; + for (SymbolTable$Entry symbolTable$Entry2 = symbolTable$Entry = this.get(value3); + symbolTable$Entry2 != null; + symbolTable$Entry2 = symbolTable$Entry = symbolTable$Entry.next) { + if (symbolTable$Entry.tag == value + && symbolTable$Entry.hashCode == value3 + && symbolTable$Entry.data == value2) { + return symbolTable$Entry; + } + } + this.constantPool.putByte(value).putInt(value2); + return this.put(new SymbolTable$Entry(this.constantPoolCount++, value, value2, value3)); + } + + public void addConstantLongOrDouble(int value, int value2, long value3) { + this.add(new SymbolTable$Entry(value, value2, value3, hash(value2, value3))); + } + + public SymbolTable$Entry addConstantMemberReference( + int value2, String text, String text2, String text3) { + int value3 = hash(value2, text, text2, text3); + SymbolTable$Entry symbolTable$Entry; + for (SymbolTable$Entry symbolTable$Entry2 = symbolTable$Entry = this.get(value3); + symbolTable$Entry2 != null; + symbolTable$Entry2 = symbolTable$Entry = symbolTable$Entry.next) { + if (symbolTable$Entry.tag == value2 + && symbolTable$Entry.hashCode == value3 + && symbolTable$Entry.owner.equals(text) + && symbolTable$Entry.name.equals(text2) + && symbolTable$Entry.value.equals(text3)) { + return symbolTable$Entry; + } + } + this.constantPool.put122( + value2, this.getSymbol3(text).index, this.addConstantNameAndType(text2, text3)); + return this.put( + new SymbolTable$Entry(this.constantPoolCount++, value2, text, text2, text3, 0L, value3)); + } + + public void addConstantIntegerOrFloat(int value, int value2, int value3) { + this.add(new SymbolTable$Entry(value, value2, value3, hash(value2, value3))); + } + + public static int hash(int value, String text, String text2, String text3) { + return 2147483647 & value + text.hashCode() * text2.hashCode() * text3.hashCode(); + } + + public static int hash(int value, String text, int value2) { + return 2147483647 & value + text.hashCode() + value2; + } + + public int addUninitializedType(String text, int value2) { + int value3 = hash(129, text, value2); + SymbolTable$Entry symbolTable$Entry; + for (SymbolTable$Entry symbolTable$Entry2 = symbolTable$Entry = this.get(value3); + symbolTable$Entry2 != null; + symbolTable$Entry2 = symbolTable$Entry = symbolTable$Entry.next) { + if (symbolTable$Entry.tag == 129 + && symbolTable$Entry.hashCode == value3 + && symbolTable$Entry.data == value2 + && symbolTable$Entry.value.equals(text)) { + return symbolTable$Entry.index; + } + } + return this.addTypeInternal(new SymbolTable$Entry(this.count5, 129, text, value2, value3)); + } + + public Label getForwardUninitializedLabel(int value) { + return this.labelEntrys2[(int) this.entrys[value].data].label; + } + + public int addConstantNameAndType(String text, String text2) { + int value2 = hash(12, text, text2); + SymbolTable$Entry symbolTable$Entry; + for (SymbolTable$Entry symbolTable$Entry2 = symbolTable$Entry = this.get(value2); + symbolTable$Entry2 != null; + symbolTable$Entry2 = symbolTable$Entry = symbolTable$Entry.next) { + if (symbolTable$Entry.tag == 12 + && symbolTable$Entry.hashCode == value2 + && symbolTable$Entry.name.equals(text) + && symbolTable$Entry.value.equals(text2)) { + return symbolTable$Entry.index; + } + } + this.constantPool.put122(12, this.addConstantUtf8(text), this.addConstantUtf8(text2)); + return this.put(new SymbolTable$Entry(this.constantPoolCount++, 12, text, text2, value2)).index; + } + + public Symbol getSymbol2(String text) { + return this.addConstantUtf8Reference(20, text); + } + + public void addConstantDynamicOrInvokeDynamicReference( + int value, int value2, String text, String text2, int value3) { + int value4 = hash(value, text, text2, value3); + this.add(new SymbolTable$Entry(value2, value, null, text, text2, value3, value4)); + } + + public Symbol addConstantFieldref(String text, String text2, String text3) { + return this.addConstantMemberReference(9, text, text2, text3); + } + + public static int hash(int value, long value2) { + return 2147483647 & value + (int) value2 + (int) (value2 >>> 32); + } + + public int getCount() { + return this.count; + } + + public Symbol addConstantInvokeDynamic( + String text, String text2, Handle handle, Object... result) { + Symbol symbol = this.addBootstrapMethod(handle, result); + return this.addConstantDynamicOrInvokeDynamicReference(18, text, text2, symbol.index); + } + + public static int hash(int value, int value2) { + return 2147483647 & value + value2; + } + + public Symbol getSymbol3(String text) { + return this.addConstantUtf8Reference(7, text); + } + + public SymbolTable$Entry put(SymbolTable$Entry symbolTable$Entry) { + if (this.count2 > this.entries.length * 3 / 4) { + int value; + int value2; + SymbolTable$Entry[] symbolTable$Entrys = + new SymbolTable$Entry[value = (value2 = this.entries.length) * 2 + 1]; + int value3; + for (int value4 = value3 = value2 - 1; value4 >= 0; value4 = --value3) { + SymbolTable$Entry symbolTable$Entry2; + SymbolTable$Entry symbolTable$Entry3 = symbolTable$Entry2 = this.entries[value3]; + while (symbolTable$Entry3 != null) { + int value5 = symbolTable$Entry2.hashCode % value; + SymbolTable$Entry symbolTable$Entry4 = symbolTable$Entry2.next; + symbolTable$Entry2.next = symbolTable$Entrys[value5]; + symbolTable$Entry3 = symbolTable$Entry4; + symbolTable$Entrys[value5] = symbolTable$Entry2; + symbolTable$Entry2 = symbolTable$Entry4; + } + } + this.entries = symbolTable$Entrys; + } + this.count2++; + int value6 = symbolTable$Entry.hashCode % this.entries.length; + symbolTable$Entry.next = this.entries[value6]; + return this.entries[value6] = symbolTable$Entry; + } + + public void copyBootstrapMethods(ClassReader classReader, char[] values) { + SymbolTable symbolTable; + byte[] values2 = classReader.classFileBuffer; + int value; + int value2; + int value3 = value2 = classReader.readUnsignedShort((value = classReader.calculateCount()) - 2); + while (true) { + if (value3 <= 0) { + symbolTable = this; + break; + } + String text2 = classReader.getText2(value, values); + if ("BootstrapMethods".equals(text2)) { + symbolTable = this; + this.count4 = classReader.readUnsignedShort(value + 6); + break; + } + int value4 = classReader.readInt(value + 2); + int value5 = value; + value2--; + value = value5 + (byte) 6 + value4; + value3 = value2; + } + if (symbolTable.count4 > 0) { + int value6 = value + 8; + int value7 = classReader.readInt(value + 2) - 2; + this.byteVector = new ByteVector(value7); + this.byteVector.putByteArray(values2, value6, value7); + int value8 = value6; + int value9 = 0; + for (value3 = value9; value3 < this.count4; value3 = value9) { + int value10 = value8 - value6; + int value11 = value8; + value8 += 2; + int value12 = classReader.readUnsignedShort(value11); + int value13 = classReader.readUnsignedShort(value8); + Object result = classReader.readConst(value12, values); + value8 += 2; + int value14 = result.hashCode(); + value3 = value13; + while (true) { + int value15 = value3; + value13--; + if (value15 <= 0) { + int value16 = value9; + value9++; + this.add(new SymbolTable$Entry(value16, 64, ((long) value10), value14 & 2147483647)); + break; + } + int value17 = classReader.readUnsignedShort(value8); + int value18 = value14; + value8 += 2; + value14 = value18 ^ classReader.readConst(value17, values).hashCode(); + value3 = value13; + } + } + } + } + + public void addConstantUtf8(int value, String text) { + this.add(new SymbolTable$Entry(value, 1, text, hash(1, text))); + } + + public Symbol addConstantDynamic(String text, String text2, Handle handle, Object... result) { + Symbol symbol = this.addBootstrapMethod(handle, result); + return this.addConstantDynamicOrInvokeDynamicReference(17, text, text2, symbol.index); + } + + public void addConstantMemberReference( + int value, int value2, String text, String text2, String text3) { + this.add( + new SymbolTable$Entry( + value, value2, text, text2, text3, 0L, hash(value2, text, text2, text3))); + } + + public void addConstantMethodHandle( + int value, int value2, String text, String text2, String text3, boolean matches) { + int constantMethodHandleSymbolData = getConstantMethodHandleSymbolData(value2, matches); + int value3 = hash(15, text, text2, text3, constantMethodHandleSymbolData); + this.add( + new SymbolTable$Entry( + value, 15, text, text2, text3, constantMethodHandleSymbolData, value3)); + } + + public Symbol addConstantDouble(double value) { + return this.addConstantLongOrDouble(6, Double.doubleToRawLongBits(value)); + } + + public Symbol addConstant(Object result) { + if (result instanceof Integer) { + return this.getSymbol((Integer) result); + } + if (result instanceof Byte) { + return this.getSymbol(((Byte) result).intValue()); + } + if (result instanceof Character) { + return this.getSymbol((Character) result); + } + if (result instanceof Short) { + return this.getSymbol(((Short) result).intValue()); + } + if (result instanceof Boolean) { + return this.getSymbol((Boolean) result ? 1 : 0); + } + if (result instanceof Float) { + return this.addConstantFloat((Float) result); + } + if (result instanceof Long) { + return this.addConstantLong((Long) result); + } + if (result instanceof Double) { + return this.addConstantDouble((Double) result); + } + if (result instanceof String) { + return this.getSymbol5((String) result); + } + if (result instanceof Type) { + Type type; + int value; + if ((value = (type = (Type) result).getSort()) == 10) { + return this.getSymbol3(type.getInternalName()); + } else { + return value == 11 + ? this.getSymbol(type.getDescriptor()) + : this.getSymbol3(type.getDescriptor()); + } + } else if (result instanceof Handle) { + Handle handle = (Handle) result; + return this.addConstantMethodHandle( + handle.getTag(), + handle.getOwner(), + handle.getName(), + handle.getDescriptor(), + handle.isInterface()); + } else if (result instanceof ConstantDynamic) { + ConstantDynamic constantDynamic = (ConstantDynamic) result; + return this.addConstantDynamic( + constantDynamic.getName(), + constantDynamic.getDescriptor(), + constantDynamic.getBootstrapMethod(), + constantDynamic.getBootstrapMethodArgumentsUnsafe()); + } else { + throw new IllegalArgumentException(stringConcat$0(String.valueOf(result))); + } + } + + public Symbol addConstantLong(long value) { + return this.addConstantLongOrDouble(5, value); + } + + public Symbol addConstantFloat(float value) { + return this.addConstantIntegerOrFloat(4, Float.floatToRawIntBits(value)); + } + + public Symbol getSymbol4(String text) { + return this.addConstantUtf8Reference(19, text); + } + + public String getClassName() { + return this.className; + } + + public void processByteVector2(ByteVector byteVector2) { + if (this.byteVector != null) { + byteVector2 + .putShort(this.addConstantUtf8("BootstrapMethods")) + .putInt(this.byteVector.length + 2) + .putShort(this.count4) + .putByteArray(this.byteVector.data, 0, this.byteVector.length); + } + } + + public Symbol getSymbol5(String text) { + return this.addConstantUtf8Reference(8, text); + } + + public SymbolTable$Entry get(int value) { + return this.entries[value % this.entries.length]; + } + + public SymbolTable$LabelEntry getOrAddLabelEntry(Label label2) { + if (this.labelEntrys == null) { + this.labelEntrys = new SymbolTable$LabelEntry[16]; + this.labelEntrys2 = new SymbolTable$LabelEntry[16]; + } + int value = System.identityHashCode(label2); + SymbolTable$LabelEntry symbolTable$LabelEntry; + SymbolTable$LabelEntry symbolTable$LabelEntry2 = + symbolTable$LabelEntry = this.labelEntrys[value % this.labelEntrys.length]; + while (symbolTable$LabelEntry2 != null && symbolTable$LabelEntry.label != label2) { + symbolTable$LabelEntry2 = symbolTable$LabelEntry = symbolTable$LabelEntry.next; + } + if (symbolTable$LabelEntry != null) { + return symbolTable$LabelEntry; + } + if (this.count3 > this.labelEntrys.length * 3 / 4) { + int value2; + int value3; + SymbolTable$LabelEntry[] symbolTable$LabelEntrys = + new SymbolTable$LabelEntry[value3 = (value2 = this.labelEntrys.length) * 2 + 1]; + int value4; + for (int value5 = value4 = value2 - 1; value5 >= 0; value5 = --value4) { + SymbolTable$LabelEntry symbolTable$LabelEntry3; + symbolTable$LabelEntry2 = symbolTable$LabelEntry3 = this.labelEntrys[value4]; + while (symbolTable$LabelEntry2 != null) { + int value6 = System.identityHashCode(symbolTable$LabelEntry3.label) % value3; + SymbolTable$LabelEntry symbolTable$LabelEntry4 = symbolTable$LabelEntry3.next; + symbolTable$LabelEntry3.next = symbolTable$LabelEntrys[value6]; + symbolTable$LabelEntry2 = symbolTable$LabelEntry4; + symbolTable$LabelEntrys[value6] = symbolTable$LabelEntry3; + symbolTable$LabelEntry3 = symbolTable$LabelEntry4; + } + } + this.labelEntrys = symbolTable$LabelEntrys; + } + if (this.count3 == this.labelEntrys2.length) { + SymbolTable$LabelEntry[] symbolTable$LabelEntrys2 = + new SymbolTable$LabelEntry[2 * this.labelEntrys2.length]; + System.arraycopy(this.labelEntrys2, 0, symbolTable$LabelEntrys2, 0, this.labelEntrys2.length); + this.labelEntrys2 = symbolTable$LabelEntrys2; + } + SymbolTable$LabelEntry symbolTable$LabelEntry5 = + new SymbolTable$LabelEntry(this.count3, label2); + int value7 = value % this.labelEntrys.length; + symbolTable$LabelEntry5.next = this.labelEntrys[value7]; + this.labelEntrys[value7] = symbolTable$LabelEntry5; + this.labelEntrys2[this.count3++] = symbolTable$LabelEntry5; + return symbolTable$LabelEntry5; + } + + public Symbol addConstantMethodref(String text, String text2, String text3, boolean matches) { + int value = matches ? 11 : 10; + return this.addConstantMemberReference(value, text, text2, text3); + } + + public int computeBootstrapMethodsSize() { + if (this.byteVector != null) { + this.addConstantUtf8("BootstrapMethods"); + return 8 + this.byteVector.length; + } else { + return 0; + } + } + + public static int hash(int value, String text, String text2, int value2) { + return 2147483647 & value + text.hashCode() * text2.hashCode() * (value2 + 1); + } + + public void add(SymbolTable$Entry symbolTable$Entry) { + this.count2++; + int value = symbolTable$Entry.hashCode % this.entries.length; + symbolTable$Entry.next = this.entries[value]; + this.entries[value] = symbolTable$Entry; + } + + public int calculateCount() { + return this.constantPool.length; + } + + public Symbol addBootstrapMethod(int value, int value2, int value3) { + int value4; + byte[] values = this.byteVector.data; + SymbolTable$Entry symbolTable$Entry; + for (SymbolTable$Entry symbolTable$Entry2 = symbolTable$Entry = this.get(value3); + symbolTable$Entry2 != null; + symbolTable$Entry2 = symbolTable$Entry = symbolTable$Entry.next) { + if (symbolTable$Entry.tag == 64 && symbolTable$Entry.hashCode == value3) { + int value5 = (int) symbolTable$Entry.data; + byte value6 = 1; + int value7; + int value8 = value7 = 0; + while (true) { + if (value8 >= value2) { + value4 = value6; + break; + } + if (values[value + value7] != values[value5 + value7]) { + value4 = 0; + break; + } + value8 = ++value7; + } + if (value4 != 0) { + this.byteVector.length = value; + return symbolTable$Entry; + } + } + } + return this.put(new SymbolTable$Entry(this.count4++, 64, value, value3)); + } + + public static String stringConcat$0(String text) { + return "value " + text; + } + + public static int hash(int value, String text, String text2, String text3, int value2) { + return 2147483647 & value + text.hashCode() * text2.hashCode() * text3.hashCode() * value2; + } +} diff --git a/src/main/java/com/allatori/lib/asm/Type.java b/src/main/java/com/allatori/lib/asm/Type.java new file mode 100644 index 0000000..aed166c --- /dev/null +++ b/src/main/java/com/allatori/lib/asm/Type.java @@ -0,0 +1,633 @@ +package com.allatori.lib.asm; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; + +public final class Type { + + public static final String TEXT = "VZCBSIFJD"; + + public static final Type VOID_TYPE = new Type(0, "VZCBSIFJD", 0, 1); + + public static final Type BOOLEAN_TYPE = new Type(1, "VZCBSIFJD", 1, 2); + + public static final Type CHAR_TYPE = new Type(2, "VZCBSIFJD", 2, 3); + + public static final Type BYTE_TYPE = new Type(3, "VZCBSIFJD", 3, 4); + + public static final Type SHORT_TYPE = new Type(4, "VZCBSIFJD", 4, 5); + + public static final Type INT_TYPE = new Type(5, "VZCBSIFJD", 5, 6); + + public static final Type FLOAT_TYPE = new Type(6, "VZCBSIFJD", 6, 7); + + public static final Type LONG_TYPE = new Type(7, "VZCBSIFJD", 7, 8); + + public static final Type DOUBLE_TYPE = new Type(8, "VZCBSIFJD", 8, 9); + + public static final int LONG = 7; + + public static final int OBJECT = 10; + + public static final int DOUBLE = 8; + + public static final int ARRAY = 9; + + public static final int BOOLEAN = 1; + + public final String valueBuffer; + + public static final int CHAR = 2; + + public static final int FLOAT = 6; + + public static final int INTERNAL = 12; + + public static final int METHOD = 11; + + public static final int BYTE = 3; + + public final int valueBegin; + + public static final int SHORT = 4; + + public static final int VOID = 0; + + public final int sort; + + public final int valueEnd; + + public static final int INT = 5; + + public static int getArgumentsAndReturnSizes(String text) { + int value = 1; + int value2 = 1; + char value3; + char value4 = value3 = text.charAt(value2); + while (value4 != ')') { + String text2; + if (value3 != 'J' && value3 != 'D') { + String text3 = text; + while (text3.charAt(value2) == '[') { + value2++; + text3 = text; + } + value4 = text.charAt(value2); + char value5 = value4; + value2++; + if (value5 == (byte) 76) { + int value6 = text.indexOf(59, value2); + value2 = Math.max(value2, value6 + 1); + } + value++; + text2 = text; + } else { + value2++; + value += 2; + text2 = text; + } + value4 = value3 = text2.charAt(value2); + } + char value7; + if ((value7 = text.charAt(value2 + 1)) == 'V') { + return value << 2; + } + int value8 = value7 != 'J' && value7 != 'D' ? 1 : 2; + return value << 2 | value8; + } + + public void appendDescriptor(StringBuilder stringBuilder) { + if (this.sort == 10) { + stringBuilder.append(this.valueBuffer, this.valueBegin - 1, this.valueEnd + 1); + } else if (this.sort == 12) { + stringBuilder + .append('L') + .append(this.valueBuffer, this.valueBegin, this.valueEnd) + .append(';'); + } else { + stringBuilder.append(this.valueBuffer, this.valueBegin, this.valueEnd); + } + } + + public static int getReturnTypeOffset(String text) { + int value = 1; + label26: + while (true) { + String text2 = text; + while (text2.charAt(value) != ')') { + text2 = text; + while (text2.charAt(value) == '[') { + value++; + text2 = text; + } + char value2 = text.charAt(value); + value++; + if (value2 != (byte) 76) { + continue label26; + } + text2 = text; + int value3 = text.indexOf(59, value); + value = Math.max(value, value3 + 1); + } + return value + 1; + } + } + + public Type(int sort, String valueBuffer, int valueBegin, int valueEnd) { + super(); + this.sort = sort; + this.valueBuffer = valueBuffer; + this.valueBegin = valueBegin; + this.valueEnd = valueEnd; + } + + public static void appendDescriptor(Class classValue, StringBuilder stringBuilder) { + Class classValue2; + for (Class classValue3 = classValue2 = classValue; + classValue3.isArray(); + classValue3 = classValue2) { + stringBuilder.append('['); + classValue2 = classValue2.getComponentType(); + } + if (classValue2.isPrimitive()) { + char value; + StringBuilder stringBuilder2; + if (classValue2 == int.class) { + value = 'I'; + stringBuilder2 = stringBuilder; + } else if (classValue2 == void.class) { + value = 'V'; + stringBuilder2 = stringBuilder; + } else if (classValue2 == boolean.class) { + value = 'Z'; + stringBuilder2 = stringBuilder; + } else if (classValue2 == byte.class) { + value = 'B'; + stringBuilder2 = stringBuilder; + } else if (classValue2 == char.class) { + value = 'C'; + stringBuilder2 = stringBuilder; + } else if (classValue2 == short.class) { + value = 'S'; + stringBuilder2 = stringBuilder; + } else if (classValue2 == double.class) { + value = 'D'; + stringBuilder2 = stringBuilder; + } else if (classValue2 == float.class) { + value = 'F'; + stringBuilder2 = stringBuilder; + } else { + if (classValue2 != long.class) { + throw new AssertionError(); + } + value = 'J'; + stringBuilder2 = stringBuilder; + } + stringBuilder2.append(value); + } else { + stringBuilder.append('L').append(getText(classValue2)).append(';'); + } + } + + public int getSize() { + switch (this.sort) { + case 0: + return 0; + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 9: + case 10: + case 12: + return 1; + case 7: + case 8: + return 2; + case 11: + default: + throw new AssertionError(); + } + } + + public static String getText(Class classValue) { + return classValue.getName().replace('.', '/'); + } + + public static String createText(String text) { + return "Invalid descriptor: " + text; + } + + public int getArgumentsAndReturnSizes() { + return getArgumentsAndReturnSizes(this.getDescriptor()); + } + + public int getSort() { + return this.sort == 12 ? 10 : this.sort; + } + + public static Type getType(Class classValue) { + if (classValue.isPrimitive()) { + if (classValue == int.class) { + return INT_TYPE; + } else if (classValue == void.class) { + return VOID_TYPE; + } else if (classValue == boolean.class) { + return BOOLEAN_TYPE; + } else if (classValue == byte.class) { + return BYTE_TYPE; + } else if (classValue == char.class) { + return CHAR_TYPE; + } else if (classValue == short.class) { + return SHORT_TYPE; + } else if (classValue == double.class) { + return DOUBLE_TYPE; + } else if (classValue == float.class) { + return FLOAT_TYPE; + } else if (classValue == long.class) { + return LONG_TYPE; + } else { + throw new AssertionError(); + } + } else { + return getType(createText(classValue)); + } + } + + public static Type getType(Constructor constructor) { + return getType(getConstructorDescriptor(constructor)); + } + + public static Type[] getArgumentTypes(Method method) { + Class[] classs; + Type[] types = new Type[(classs = method.getParameterTypes()).length]; + int value; + for (int value2 = value = classs.length - 1; value2 >= 0; value2 = value) { + Type type = getType(classs[value]); + int value3 = value; + value--; + types[value3] = type; + } + return types; + } + + public static Type getType(Method method) { + return getType(method.getReturnType()); + } + + public static Type[] getArgumentTypes(String text) { + Type[] types = new Type[getArgumentCount(text)]; + int value = 1; + int value2 = 0; + for (String text2 = text; text2.charAt(value) != ')'; text2 = text) { + int value3 = value; + text2 = text; + while (text2.charAt(value) == '[') { + value++; + text2 = text; + } + char value4 = text.charAt(value); + value++; + if (value4 == (byte) 76) { + int value5 = text.indexOf(59, value); + value = Math.max(value, value5 + 1); + } + int value6 = value; + int value7 = value2; + value2++; + types[value7] = getTypeInternal(text, value3, value6); + } + return types; + } + + public static String getConstructorDescriptor(Constructor constructor) { + StringBuilder stringBuilder; + (stringBuilder = new StringBuilder()).append('('); + Class[] parameterTypes = constructor.getParameterTypes(); + int value = parameterTypes.length; + int value2; + for (int value3 = value2 = 0; value3 < value; value3 = value2) { + int value4 = value2; + value2++; + appendDescriptor(parameterTypes[value4], stringBuilder); + } + return stringBuilder.append(")V").toString(); + } + + public static Type getReturnType(Method method) { + return getType(getMethodDescriptor(method)); + } + + public static Type getObjectType(String text) { + return new Type(text.charAt(0) == '[' ? 9 : 12, text, 0, text.length()); + } + + public int getArgumentCount() { + return getArgumentCount(this.getDescriptor()); + } + + public int getDimensions() { + int value = 1; + Type type = this; + while (type.valueBuffer.charAt(this.valueBegin + value) == '[') { + value++; + type = this; + } + return value; + } + + public Type[] getArgumentTypes() { + return getArgumentTypes(this.getDescriptor()); + } + + public static Type getTypeInternal(String text, int value, int value2) { + switch (text.charAt(value)) { + case '(': + return new Type(11, text, value, value2); + case 'B': + return BYTE_TYPE; + case 'C': + return CHAR_TYPE; + case 'D': + return DOUBLE_TYPE; + case 'F': + return FLOAT_TYPE; + case 'I': + return INT_TYPE; + case 'J': + return LONG_TYPE; + case 'L': + return new Type(10, text, value + 1, value2 - 1); + case 'S': + return SHORT_TYPE; + case 'V': + return VOID_TYPE; + case 'Z': + return BOOLEAN_TYPE; + case '[': + return new Type(9, text, value, value2); + default: + throw new IllegalArgumentException(createText(text)); + } + } + + public String getClassName() { + switch (this.sort) { + case 0: + return "void"; + case 1: + return "boolean"; + case 2: + return "char"; + case 3: + return "byte"; + case 4: + return "short"; + case 5: + return "int"; + case 6: + return "float"; + case 7: + return "long"; + case 8: + return "double"; + case 9: + StringBuilder stringBuilder = new StringBuilder(this.getElementType().getClassName()); + int value; + for (int value2 = value = this.getDimensions(); value2 > 0; value2 = value) { + value--; + stringBuilder.append("[]"); + } + return stringBuilder.toString(); + case 10: + case 12: + return this.valueBuffer.substring(this.valueBegin, this.valueEnd).replace('/', '.'); + case 11: + default: + throw new AssertionError(); + } + } + + public Type getElementType() { + int dimensions = this.getDimensions(); + return getTypeInternal(this.valueBuffer, this.valueBegin + dimensions, this.valueEnd); + } + + public static String getMethodDescriptor(Method method) { + StringBuilder stringBuilder; + (stringBuilder = new StringBuilder()).append('('); + Class[] parameterTypes = method.getParameterTypes(); + int value = parameterTypes.length; + int value2; + for (int value3 = value2 = 0; value3 < value; value3 = value2) { + int value4 = value2; + value2++; + appendDescriptor(parameterTypes[value4], stringBuilder); + } + stringBuilder.append(')'); + appendDescriptor(method.getReturnType(), stringBuilder); + return stringBuilder.toString(); + } + + public static String createText2(String text) { + return "L" + text + ";"; + } + + public static Type getType(String text) { + return getTypeInternal(text, 0, text.length()); + } + + public static int getArgumentCount(String text) { + int value = 0; + int value2 = 1; + for (String text2 = text; text2.charAt(value2) != ')'; text2 = text) { + text2 = text; + while (text2.charAt(value2) == '[') { + value2++; + text2 = text; + } + char value3 = text.charAt(value2); + value2++; + if (value3 == (byte) 76) { + int value4 = text.indexOf(59, value2); + value2 = Math.max(value2, value4 + 1); + } + value++; + } + return value; + } + + public static Type getReturnType(String text) { + return getTypeInternal(text, getReturnTypeOffset(text), text.length()); + } + + public Type getReturnType() { + return getReturnType(this.getDescriptor()); + } + + public String getInternalName() { + return this.valueBuffer.substring(this.valueBegin, this.valueEnd); + } + + public int getOpcode(int value) { + if (value != 46 && value != 79) { + switch (this.sort) { + case 0: + if (value != 172) { + throw new UnsupportedOperationException(); + } + return 177; + case 1: + case 2: + case 3: + case 4: + case 5: + return value; + case 6: + return value + 2; + case 7: + return value + 1; + case 8: + return value + 3; + case 9: + case 10: + case 12: + if (value != 21 && value != 54 && value != 172) { + throw new UnsupportedOperationException(); + } + return value + 4; + case 11: + throw new UnsupportedOperationException(); + default: + throw new AssertionError(); + } + } else { + switch (this.sort) { + case 0: + case 11: + throw new UnsupportedOperationException(); + case 1: + case 3: + return value + 5; + case 2: + return value + 6; + case 4: + return value + 7; + case 5: + return value; + case 6: + return value + 2; + case 7: + return value + 1; + case 8: + return value + 3; + case 9: + case 10: + case 12: + return value + 4; + default: + throw new AssertionError(); + } + } + } + + public String getDescriptor() { + if (this.sort == 10) { + return this.valueBuffer.substring(this.valueBegin - 1, this.valueEnd + 1); + } else { + return this.sort == 12 + ? createText2(this.valueBuffer.substring(this.valueBegin, this.valueEnd)) + : this.valueBuffer.substring(this.valueBegin, this.valueEnd); + } + } + + public static Type getMethodType(Type type, Type... type2) { + return getType(getMethodDescriptor(type, (Type[]) type2)); + } + + @Override + public boolean equals(Object result) { + if (this == result) { + return true; + } + if (!(result instanceof Type)) { + return false; + } + Type type = (Type) result; + int value; + Type type2; + if (this.sort == 12) { + value = 10; + type2 = type; + } else { + value = this.sort; + type2 = type; + } + if (value != (type2.sort == 12 ? 10 : type.sort)) { + return false; + } + int value2 = this.valueBegin; + int value3 = this.valueEnd; + int value4 = type.valueBegin; + int value5 = type.valueEnd; + if (value3 - value2 != value5 - value4) { + return false; + } + int value6 = value2; + int value7 = value4; + value = value6; + while (value < value3) { + if (this.valueBuffer.charAt(value6) != type.valueBuffer.charAt(value7)) { + return false; + } + int value8 = ++value6; + value7++; + value = value8; + } + return true; + } + + public static String getMethodDescriptor(Type type, Type... type2) { + StringBuilder stringBuilder; + (stringBuilder = new StringBuilder()).append('('); + int value = ((Type[]) type2).length; + int value2; + for (int value3 = value2 = 0; value3 < value; value3 = value2) { + int value4 = value2; + Type[] types = (Type[]) type2; + value2++; + types[value4].appendDescriptor(stringBuilder); + } + stringBuilder.append(')'); + type.appendDescriptor(stringBuilder); + return stringBuilder.toString(); + } + + public static Type getMethodType(String text) { + return new Type(11, text, 0, text.length()); + } + + @Override + public int hashCode() { + int value = 13 * (this.sort == 12 ? 10 : this.sort); + if (this.sort >= 9) { + int value2 = this.valueBegin; + int value3 = this.valueEnd; + for (int value4 = value2; value4 < value3; value4 = value2) { + char value5 = this.valueBuffer.charAt(value2); + int value6 = value; + value2++; + value = (byte) 17 * (value6 + value5); + } + } + return value; + } + + public static String createText(Class classValue) { + StringBuilder stringBuilder = new StringBuilder(); + appendDescriptor(classValue, stringBuilder); + return stringBuilder.toString(); + } +} diff --git a/src/main/java/com/allatori/lib/asm/TypePath.java b/src/main/java/com/allatori/lib/asm/TypePath.java new file mode 100644 index 0000000..49d698a --- /dev/null +++ b/src/main/java/com/allatori/lib/asm/TypePath.java @@ -0,0 +1,97 @@ +package com.allatori.lib.asm; + +public final class TypePath { + + public final int typePathOffset; + + public final byte[] typePathContainer; + + public static final int INNER_TYPE = 1; + + public static final int WILDCARD_BOUND = 2; + + public static final int TYPE_ARGUMENT = 3; + + public static final int ARRAY_ELEMENT = 0; + + public static TypePath fromString(String text) { + if (text != null && text.length() != 0) { + int size = text.length(); + ByteVector byteVector; + (byteVector = new ByteVector(size)).putByte(0); + int value = 0; + while (value < size) { + char value2; + char value3 = value2 = text.charAt(value); + value++; + if (value3 == '[') { + byteVector.put11(0, 0); + } else if (value2 != '.') { + if (value2 != '*') { + if (value2 < '0' || value2 > '9') { + throw new IllegalArgumentException(); + } + int value4 = value2 - '0'; + int value5 = value; + while (true) { + ByteVector byteVector2; + if (value5 < size) { + char value6; + char value7 = value6 = text.charAt(value); + value++; + if (value7 >= '0' && value6 <= '9') { + value4 = value4 * 10 + value6 - 48; + value5 = value; + continue; + } + if (value6 != ';') { + throw new IllegalArgumentException(); + } + byteVector2 = byteVector; + } else { + byteVector2 = byteVector; + } + byteVector2.put11(3, value4); + break; + } + } else { + byteVector.put11(2, 0); + } + } else { + byteVector.put11(1, 0); + } + } + byteVector.data[0] = (byte) (byteVector.length / 2); + return new TypePath(byteVector.data, 0); + } else { + return null; + } + } + + public int calculateCount(int value) { + return this.typePathContainer[this.typePathOffset + 2 * value + 1]; + } + + public int getLength() { + return this.typePathContainer[this.typePathOffset]; + } + + public int calculateCount2(int value) { + return this.typePathContainer[this.typePathOffset + 2 * value + 2]; + } + + public static void put(TypePath typePath, ByteVector byteVector) { + if (typePath == null) { + byteVector.putByte(0); + } else { + int value = typePath.typePathContainer[typePath.typePathOffset] * 2 + 1; + byteVector.putByteArray(typePath.typePathContainer, typePath.typePathOffset, value); + } + } + + public TypePath(byte[] typePathContainer, int typePathOffset) { + super(); + this.typePathContainer = typePathContainer; + this.typePathOffset = typePathOffset; + } +} diff --git a/src/main/java/com/allatori/lib/asm/TypeReference.java b/src/main/java/com/allatori/lib/asm/TypeReference.java new file mode 100644 index 0000000..e599b17 --- /dev/null +++ b/src/main/java/com/allatori/lib/asm/TypeReference.java @@ -0,0 +1,213 @@ +package com.allatori.lib.asm; + +public class TypeReference { + + public static final int METHOD_TYPE_PARAMETER = 1; + + public static final int METHOD_INVOCATION_TYPE_ARGUMENT = 73; + + public static final int RESOURCE_VARIABLE = 65; + + public static final int THROWS = 23; + + public static final int CONSTRUCTOR_REFERENCE = 69; + + public static final int METHOD_REFERENCE_TYPE_ARGUMENT = 75; + + public static final int CAST = 71; + + public static final int FIELD = 19; + + public final int targetTypeAndInfo; + + public static final int METHOD_FORMAL_PARAMETER = 22; + + public static final int CLASS_TYPE_PARAMETER_BOUND = 17; + + public static final int LOCAL_VARIABLE = 64; + + public static final int CLASS_TYPE_PARAMETER = 0; + + public static final int INSTANCEOF = 67; + + public static final int METHOD_REFERENCE = 70; + + public static final int CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT = 72; + + public static final int EXCEPTION_PARAMETER = 66; + + public static final int NEW = 68; + + public static final int METHOD_TYPE_PARAMETER_BOUND = 18; + + public static final int METHOD_RECEIVER = 21; + + public static final int CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT = 74; + + public static final int METHOD_RETURN = 20; + + public static final int CLASS_EXTENDS = 16; + + public static TypeReference createTypeReference(int value) { + return new TypeReference(1107296256 | value << 8); + } + + public static TypeReference createTypeReference2(int value) { + return new TypeReference(385875968 | value << 8); + } + + public static void putTarget(int value, ByteVector byteVector) { + switch (value >>> 24) { + case 0: + case 1: + case 22: + byteVector.putShort(value >>> 16); + return; + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + case 24: + case 25: + case 26: + case 27: + case 28: + case 29: + case 30: + case 31: + case 32: + case 33: + case 34: + case 35: + case 36: + case 37: + case 38: + case 39: + case 40: + case 41: + case 42: + case 43: + case 44: + case 45: + case 46: + case 47: + case 48: + case 49: + case 50: + case 51: + case 52: + case 53: + case 54: + case 55: + case 56: + case 57: + case 58: + case 59: + case 60: + case 61: + case 62: + case 63: + case 64: + case 65: + default: + throw new IllegalArgumentException(); + case 16: + case 17: + case 18: + case 23: + case 66: + case 67: + case 68: + case 69: + case 70: + byteVector.put12(value >>> 24, (value & 16776960) >> 8); + return; + case 19: + case 20: + case 21: + byteVector.putByte(value >>> 24); + return; + case 71: + case 72: + case 73: + case 74: + case 75: + byteVector.putInt(value); + } + } + + public int getTargetTypeAndInfo() { + return this.targetTypeAndInfo >>> 24; + } + + public int getTargetTypeAndInfo2() { + return (this.targetTypeAndInfo & 16776960) >> 8; + } + + public int getTargetTypeAndInfo3() { + return this.targetTypeAndInfo; + } + + public int getTargetTypeAndInfo4() { + return (this.targetTypeAndInfo & 0xFF0000) >> 16; + } + + public int getTargetTypeAndInfo5() { + return (this.targetTypeAndInfo & 0xFF00) >> 8; + } + + public static TypeReference newTypeParameterBoundReference(int value, int value2, int value3) { + return new TypeReference(value << 24 | value2 << 16 | value3 << 8); + } + + public TypeReference(int targetTypeAndInfo) { + super(); + this.targetTypeAndInfo = targetTypeAndInfo; + } + + public static TypeReference createTypeReference(int value, int value2) { + return new TypeReference(value << 24 | value2); + } + + public static TypeReference createTypeReference3(int value) { + return new TypeReference(value << 24); + } + + public static TypeReference createTypeReference2(int value, int value2) { + return new TypeReference(value << 24 | value2 << 16); + } + + public int getTargetTypeAndInfo6() { + return (short) ((this.targetTypeAndInfo & 16776960) >> 8); + } + + public int getTargetTypeAndInfo7() { + return (this.targetTypeAndInfo & 0xFF0000) >> 16; + } + + public int getTargetTypeAndInfo8() { + return (this.targetTypeAndInfo & 16776960) >> 8; + } + + public int getTargetTypeAndInfo9() { + return this.targetTypeAndInfo & 0xFF; + } + + public static TypeReference createTypeReference4(int value) { + return new TypeReference(369098752 | value << 16); + } + + public static TypeReference createTypeReference5(int value) { + return new TypeReference(268435456 | (value & 65535) << 8); + } +} diff --git a/src/main/java/com/allatori/lib/asm/signature/SignatureReader.java b/src/main/java/com/allatori/lib/asm/signature/SignatureReader.java new file mode 100644 index 0000000..74e834c --- /dev/null +++ b/src/main/java/com/allatori/lib/asm/signature/SignatureReader.java @@ -0,0 +1,182 @@ +package com.allatori.lib.asm.signature; + +public class SignatureReader { + + public final String signatureValue; + + public static int parseType(String text, int value, SignatureVisitor signatureVisitor) { + char value2; + int value3 = value; + char value4; + char value5 = value4 = text.charAt(value3); + value3++; + switch (value5) { + case 'B': + case 'C': + case 'D': + case 'F': + case 'I': + case 'J': + case 'S': + case 'V': + case 'Z': + signatureVisitor.visitBaseType(value4); + return value3; + case 'E': + case 'G': + case 'H': + case 'K': + case 'M': + case 'N': + case 'O': + case 'P': + case 'Q': + case 'R': + case 'U': + case 'W': + case 'X': + case 'Y': + default: + throw new IllegalArgumentException(); + case 'L': + int value6 = value3; + byte value7 = 0; + byte value8 = 0; + while (true) { + String text2 = text; + while (true) { + char value9; + char value10 = value9 = text2.charAt(value3); + value3++; + if (value10 != '.' && value9 != ';') { + if (value9 == '<') { + String text3 = text.substring(value6, value3 - 1); + if (value8 != 0) { + signatureVisitor.processText2(text3); + } else { + signatureVisitor.processText(text3); + } + value7 = 1; + text2 = text; + char value11; + while ((value11 = text2.charAt(value3)) != '>') { + switch (value11) { + case '*': + value3++; + text2 = text; + signatureVisitor.update2(); + break; + case '+': + case '-': + text2 = text; + value3 = + parseType(text, value3 + 1, signatureVisitor.visitTypeArgument(value11)); + break; + case ',': + default: + text2 = text; + value3 = parseType(text, value3, signatureVisitor.visitTypeArgument('=')); + } + } + } + break; + } + label45: + { + if (value7 == 0) { + String text4 = text.substring(value6, value3 - 1); + if (value8 != 0) { + signatureVisitor.processText2(text4); + value2 = value9; + break label45; + } + signatureVisitor.processText(text4); + } + value2 = value9; + } + if (value2 == ';') { + signatureVisitor.update(); + return value3; + } + value6 = value3; + value7 = 0; + value8 = 1; + text2 = text; + } + } + case 'T': + int value12; + int value13 = value12 = text.indexOf(59, value3); + signatureVisitor.processText3(text.substring(value3, value12)); + return value13 + 1; + case '[': + return parseType(text, value3, signatureVisitor.getSignatureVisitor7()); + } + } + + public void acceptType(SignatureVisitor signatureVisitor) { + parseType(this.signatureValue, 0, signatureVisitor); + } + + public void accept(SignatureVisitor signatureVisitor) { + String text; + String text2 = text = this.signatureValue; + int size = this.signatureValue.length(); + int value; + if (text2.charAt(0) == '<') { + value = 2; + label59: + while (true) { + int value2 = text.indexOf(58, value); + signatureVisitor.processText4(text.substring(value - 1, value2)); + char value3; + if ((value3 = text.charAt(value = value2 + 1)) == 'L' || value3 == '[' || value3 == 'T') { + value = parseType(text, value, signatureVisitor.getSignatureVisitor5()); + } + text2 = text; + while (true) { + char value4; + char value5 = value4 = text2.charAt(value); + value++; + if (value5 != ':') { + if (value4 == '>') { + text2 = text; + break label59; + } + break; + } + text2 = text; + value = parseType(text, value, signatureVisitor.getSignatureVisitor6()); + } + } + } else { + value = 0; + text2 = text; + } + if (text2.charAt(value) == '(') { + String text3 = text; + value++; + for (String text4 = text3; + text4.charAt(value) != ')'; + value = parseType(text, value, signatureVisitor.getSignatureVisitor())) { + text4 = text; + } + int value6; + int value7 = value6 = parseType(text, value + 1, signatureVisitor.getSignatureVisitor8()); + while (value7 < size) { + value7 = value6 = parseType(text, value6 + 1, signatureVisitor.getSignatureVisitor4()); + } + } else { + int value8; + int value9 = value8 = parseType(text, value, signatureVisitor.getSignatureVisitor3()); + while (value9 < size) { + value9 = value8 = parseType(text, value8, signatureVisitor.getSignatureVisitor2()); + } + } + } + + public SignatureReader(String signatureValue) { + super(); + this.signatureValue = signatureValue; + } +} diff --git a/src/main/java/com/allatori/lib/asm/signature/SignatureVisitor.java b/src/main/java/com/allatori/lib/asm/signature/SignatureVisitor.java new file mode 100644 index 0000000..6a98740 --- /dev/null +++ b/src/main/java/com/allatori/lib/asm/signature/SignatureVisitor.java @@ -0,0 +1,80 @@ +package com.allatori.lib.asm.signature; + +public abstract class SignatureVisitor { + + public static final char INSTANCEOF = '='; + + public static final char SUPER = '-'; + + public static final char EXTENDS = '+'; + + public final int api; + + public void update() {} + + public void visitBaseType(char value) {} + + public SignatureVisitor getSignatureVisitor() { + return this; + } + + public void processText(String text) {} + + public SignatureVisitor visitTypeArgument(char value) { + return this; + } + + public static String stringConcat$0(int value) { + return "Unsupported api " + value; + } + + public void processText2(String text) {} + + public SignatureVisitor getSignatureVisitor2() { + return this; + } + + public SignatureVisitor getSignatureVisitor3() { + return this; + } + + public SignatureVisitor getSignatureVisitor4() { + return this; + } + + public SignatureVisitor getSignatureVisitor5() { + return this; + } + + public SignatureVisitor getSignatureVisitor6() { + return this; + } + + public void update2() {} + + public SignatureVisitor getSignatureVisitor7() { + return this; + } + + public SignatureVisitor(int api) { + super(); + if (api != 589824 + && api != 524288 + && api != 458752 + && api != 393216 + && api != 327680 + && api != 262144 + && api != 17432576) { + throw new IllegalArgumentException(stringConcat$0(api)); + } + this.api = api; + } + + public SignatureVisitor getSignatureVisitor8() { + return this; + } + + public void processText3(String text) {} + + public void processText4(String text) {} +} diff --git a/src/main/java/com/allatori/lib/asm/signature/SignatureWriter.java b/src/main/java/com/allatori/lib/asm/signature/SignatureWriter.java new file mode 100644 index 0000000..6da3a34 --- /dev/null +++ b/src/main/java/com/allatori/lib/asm/signature/SignatureWriter.java @@ -0,0 +1,149 @@ +package com.allatori.lib.asm.signature; + +public class SignatureWriter extends SignatureVisitor { + + public int argumentStack; + + public boolean enabled; + + public final StringBuilder stringBuilder; + + public boolean enabled2; + + @Override + public SignatureVisitor getSignatureVisitor5() { + return this; + } + + @Override + public void visitBaseType(char value) { + this.stringBuilder.append(value); + } + + public SignatureWriter(StringBuilder stringBuilder2) { + super(589824); + this.argumentStack = 1; + this.stringBuilder = stringBuilder2; + } + + @Override + public SignatureVisitor getSignatureVisitor() { + this.endFormals(); + if (!this.enabled) { + this.enabled = true; + this.stringBuilder.append('('); + } + return this; + } + + @Override + public void processText2(String text) { + this.endArguments(); + this.stringBuilder.append('.').append(text); + this.argumentStack <<= 1; + } + + @Override + public SignatureVisitor getSignatureVisitor8() { + this.endFormals(); + if (!this.enabled) { + this.stringBuilder.append('('); + } + this.stringBuilder.append(')'); + return this; + } + + @Override + public SignatureVisitor getSignatureVisitor6() { + this.stringBuilder.append(':'); + return this; + } + + @Override + public SignatureVisitor getSignatureVisitor3() { + this.endFormals(); + return this; + } + + @Override + public void processText(String text) { + this.stringBuilder.append('L').append(text); + this.argumentStack <<= 1; + } + + @Override + public void update2() { + if ((this.argumentStack & 1) == 0) { + this.argumentStack |= 1; + this.stringBuilder.append('<'); + } + this.stringBuilder.append('*'); + } + + @Override + public void update() { + this.endArguments(); + this.stringBuilder.append(';'); + } + + @Override + public SignatureVisitor visitTypeArgument(char value) { + if ((this.argumentStack & 1) == 0) { + this.argumentStack |= 1; + this.stringBuilder.append('<'); + } + if (value != '=') { + this.stringBuilder.append(value); + } + return (this.argumentStack & -2147483648) == 0 ? this : new SignatureWriter(this.stringBuilder); + } + + public SignatureWriter() { + this(new StringBuilder()); + } + + @Override + public SignatureVisitor getSignatureVisitor2() { + return this; + } + + @Override + public SignatureVisitor getSignatureVisitor7() { + this.stringBuilder.append('['); + return this; + } + + @Override + public void processText4(String text) { + if (!this.enabled2) { + this.enabled2 = true; + this.stringBuilder.append('<'); + } + this.stringBuilder.append(text).append(':'); + } + + public void endArguments() { + if ((this.argumentStack & 1) == 1) { + this.stringBuilder.append('>'); + } + this.argumentStack >>>= 1; + } + + public void endFormals() { + if (this.enabled2) { + this.enabled2 = false; + this.stringBuilder.append('>'); + } + } + + @Override + public SignatureVisitor getSignatureVisitor4() { + this.stringBuilder.append('^'); + return this; + } + + @Override + public void processText3(String text) { + this.stringBuilder.append('T').append(text).append(';'); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/Constants.java b/src/main/java/com/allatori/lib/bcel/Constants.java new file mode 100644 index 0000000..8a58971 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/Constants.java @@ -0,0 +1,1422 @@ +package com.allatori.lib.bcel; + +public interface Constants { + + short ALOAD_1 = 43; + + short RETURN = 177; + + short FMUL = 106; + + short FADD = 98; + + short IFNE = 154; + + short PUTSTATIC_QUICK = 211; + + byte VALUE = 11; + + short I2F = 134; + + short DCMPL = 151; + + byte VALUE2 = 10; + + String TEXT4 = ""; + + String TEXT2 = ""; + + String TEXT3 = ""; + + String TEXT = ""; + + String[] TEXTS9 = + new String[] { + "public", + "private", + "protected", + "static", + "final", + "synchronized", + "volatile", + "transient", + "native", + "interface", + "abstract", + "strictfp", + "synthetic", + "annotation", + "enum" + }; + + String[] TEXTS7 = + new String[] { + "", + "CONSTANT_Utf8", + "", + "CONSTANT_Integer", + "CONSTANT_Float", + "CONSTANT_Long", + "CONSTANT_Double", + "CONSTANT_Class", + "CONSTANT_String", + "CONSTANT_Fieldref", + "CONSTANT_Methodref", + "CONSTANT_InterfaceMethodref", + "CONSTANT_NameAndType", + "", + "", + "CONSTANT_MethodHandle", + "CONSTANT_MethodType", + "", + "CONSTANT_InvokeDynamic" + }; + + String[] TEXTS5 = new String[] {"java.lang.Cloneable", "java.io.Serializable"}; + + String[] TEXTS = + new String[] { + "", + "", + "", + "", + "boolean", + "char", + "float", + "double", + "byte", + "short", + "int", + "long", + "void", + "array", + "object", + "unknown", + "address" + }; + + String[] TEXTS6 = + new String[] { + "", + "", + "", + "", + "java.lang.Boolean", + "java.lang.Character", + "java.lang.Float", + "java.lang.Double", + "java.lang.Byte", + "java.lang.Short", + "java.lang.Integer", + "java.lang.Long", + "java.lang.Void", + "", + "", + "", + "" + }; + + String[] TEXTS3 = + new String[] { + "", + "", + "", + "", + "Z", + "C", + "F", + "D", + "B", + "S", + "I", + "J", + "V", + "", + "", + "" + }; + + short[] NO_OF_OPERANDS = + new short[] { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 2, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, -2, -2, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, + 4, 5, 2, 1, 2, 0, 0, 2, 2, 0, 0, -2, 3, 2, 2, 4, 4, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -3, -3 + }; + + short[][] TYPE_OF_OPERANDS = + new short[][] { + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[] {8}, + new short[] {9}, + new short[] {8}, + new short[] {9}, + new short[] {9}, + new short[] {8}, + new short[] {8}, + new short[] {8}, + new short[] {8}, + new short[] {8}, + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[] {8}, + new short[] {8}, + new short[] {8}, + new short[] {8}, + new short[] {8}, + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[] {8, 8}, + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[] {9}, + new short[] {9}, + new short[] {9}, + new short[] {9}, + new short[] {9}, + new short[] {9}, + new short[] {9}, + new short[] {9}, + new short[] {9}, + new short[] {9}, + new short[] {9}, + new short[] {9}, + new short[] {9}, + new short[] {9}, + new short[] {9}, + new short[] {9}, + new short[] {8}, + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[] {9}, + new short[] {9}, + new short[] {9}, + new short[] {9}, + new short[] {9}, + new short[] {9}, + new short[] {9}, + new short[] {9, 8, 8}, + new short[] {9, 8, 8}, + new short[] {9}, + new short[] {8}, + new short[] {9}, + new short[0], + new short[0], + new short[] {9}, + new short[] {9}, + new short[0], + new short[0], + new short[] {8}, + new short[] {9, 8}, + new short[] {9}, + new short[] {9}, + new short[] {10}, + new short[] {10}, + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0], + new short[0] + }; + + String[] TEXTS8 = + new String[] { + "nop", + "aconst_null", + "iconst_m1", + "iconst_0", + "iconst_1", + "iconst_2", + "iconst_3", + "iconst_4", + "iconst_5", + "lconst_0", + "lconst_1", + "fconst_0", + "fconst_1", + "fconst_2", + "dconst_0", + "dconst_1", + "bipush", + "sipush", + "ldc", + "ldc_w", + "ldc2_w", + "iload", + "lload", + "fload", + "dload", + "aload", + "iload_0", + "iload_1", + "iload_2", + "iload_3", + "lload_0", + "lload_1", + "lload_2", + "lload_3", + "fload_0", + "fload_1", + "fload_2", + "fload_3", + "dload_0", + "dload_1", + "dload_2", + "dload_3", + "aload_0", + "aload_1", + "aload_2", + "aload_3", + "iaload", + "laload", + "faload", + "daload", + "aaload", + "baload", + "caload", + "saload", + "istore", + "lstore", + "fstore", + "dstore", + "astore", + "istore_0", + "istore_1", + "istore_2", + "istore_3", + "lstore_0", + "lstore_1", + "lstore_2", + "lstore_3", + "fstore_0", + "fstore_1", + "fstore_2", + "fstore_3", + "dstore_0", + "dstore_1", + "dstore_2", + "dstore_3", + "astore_0", + "astore_1", + "astore_2", + "astore_3", + "iastore", + "lastore", + "fastore", + "dastore", + "aastore", + "bastore", + "castore", + "sastore", + "pop", + "pop2", + "dup", + "dup_x1", + "dup_x2", + "dup2", + "dup2_x1", + "dup2_x2", + "swap", + "iadd", + "ladd", + "fadd", + "dadd", + "isub", + "lsub", + "fsub", + "dsub", + "imul", + "lmul", + "fmul", + "dmul", + "idiv", + "ldiv", + "fdiv", + "ddiv", + "irem", + "lrem", + "frem", + "drem", + "ineg", + "lneg", + "fneg", + "dneg", + "ishl", + "lshl", + "ishr", + "lshr", + "iushr", + "lushr", + "iand", + "land", + "ior", + "lor", + "ixor", + "lxor", + "iinc", + "i2l", + "i2f", + "i2d", + "l2i", + "l2f", + "l2d", + "f2i", + "f2l", + "f2d", + "d2i", + "d2l", + "d2f", + "i2b", + "i2c", + "i2s", + "lcmp", + "fcmpl", + "fcmpg", + "dcmpl", + "dcmpg", + "ifeq", + "ifne", + "iflt", + "ifge", + "ifgt", + "ifle", + "if_icmpeq", + "if_icmpne", + "if_icmplt", + "if_icmpge", + "if_icmpgt", + "if_icmple", + "if_acmpeq", + "if_acmpne", + "goto", + "jsr", + "ret", + "tableswitch", + "lookupswitch", + "ireturn", + "lreturn", + "freturn", + "dreturn", + "areturn", + "return", + "getstatic", + "putstatic", + "getfield", + "putfield", + "invokevirtual", + "invokespecial", + "invokestatic", + "invokeinterface", + "invokedynamic", + "new", + "newarray", + "anewarray", + "arraylength", + "athrow", + "checkcast", + "instanceof", + "monitorenter", + "monitorexit", + "wide", + "multianewarray", + "ifnull", + "ifnonnull", + "goto_w", + "jsr_w", + "breakpoint", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "impdep1", + "impdep2" + }; + + int[] COUNTS2 = + new int[] { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 2, 1, 1, 1, 1, + 1, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 3, 4, 3, 4, 3, 3, 3, 3, 1, 2, 1, 2, 3, 2, + 3, 4, 2, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 1, 2, 1, 2, 2, 3, 2, 3, + 2, 3, 2, 4, 2, 4, 2, 4, 0, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 4, 2, 2, 4, 4, 1, 1, + 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 1, 1, 1, 2, 1, 2, 1, 0, 0, -2, 1, -2, -2, -2, + -2, -2, -2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, -2, 1, 1, 0, 0, 0, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -2 + }; + + int[] COUNTS = + new int[] { + 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 2, 2, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 1, 1, 1, 1, 2, + 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 4, 4, + 5, 6, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 0, 2, 1, 2, 1, 1, 2, 1, 2, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, -2, 0, -2, -2, + -2, -2, -2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -2 + }; + + String[] TEXTS4 = + new String[] { + "SourceFile", + "ConstantValue", + "Code", + "Exceptions", + "LineNumberTable", + "LocalVariableTable", + "InnerClasses", + "Synthetic", + "Deprecated", + "PMGClass", + "Signature", + "StackMap", + "RuntimeVisibleAnnotations", + "RuntimeInvisibleAnnotations", + "RuntimeVisibleParameterAnnotations", + "RuntimeInvisibleParameterAnnotations", + "AnnotationDefault", + "LocalVariableTypeTable", + "EnclosingMethod", + "StackMapTable", + "BootstrapMethods", + "MethodParameters", + "NestHost", + "NestMembers" + }; + + String[] TEXTS2 = + new String[] { + "Bogus", "Integer", "Float", "Double", "Long", "Null", "InitObject", "Object", "NewObject" + }; + + short ILOAD_1 = 27; + + short LASTORE = 80; + + short VALUE3 = 128; + + short INSTANCEOF = 193; + + short INEG = 116; + + byte VALUE4 = 6; + + short ILOAD = 21; + + short VALUE5 = 16384; + + short PUSH = 4711; + + short F2D = 141; + + short DDIV = 111; + + short LSTORE = 55; + + byte VALUE6 = 3; + + short VALUE7 = 0; + + byte VALUE8 = 11; + + short VALUE9 = 0; + + short LDC_W = 19; + + short ICONST_3 = 6; + + byte VALUE10 = 1; + + short DCMPG = 152; + + short MONITOREXIT = 195; + + short FSUB = 102; + + short DLOAD_1 = 39; + + int COUNT = 247; + + short VALUE11 = 3; + + byte VALUE12 = 3; + + short VALUE13 = 45; + + short IADD = 96; + + byte VALUE14 = 9; + + short TABLESWITCH = 170; + + short IREM = 112; + + short LSTORE_2 = 65; + + short LDC_W_QUICK = 204; + + int COUNT2 = 255; + + byte VALUE15 = 8; + + short DUP2_X1 = 93; + + short GETFIELD = 180; + + short VALUE16 = 128; + + short ASTORE_3 = 78; + + short ACC_NATIVE = 256; + + short VALUE17 = 3; + + short ACC_ABSTRACT = 1024; + + short DUP_X1 = 90; + + short VALUE18 = 46; + + short ISUB = 100; + + short FSTORE_3 = 70; + + short VALUE19 = 0; + + byte VALUE20 = 14; + + short RESERVED = -3; + + short DADD = 99; + + short LCONST_1 = 10; + + int COUNT3 = 251; + + int COUNT4 = 63; + + short GETFIELD2_QUICK = 208; + + short DSTORE_2 = 73; + + short LMUL = 105; + + short FNEG = 118; + + short FSTORE_0 = 67; + + short ISTORE_1 = 60; + + int COUNT5 = 252; + + byte VALUE21 = 18; + + short VALUE22 = 2; + + short FSTORE_2 = 69; + + short FLOAD_2 = 36; + + short PUTSTATIC = 179; + + short VALUE23 = 32; + + short LUSHR = 125; + + short UNPREDICTABLE = -2; + + byte VALUE24 = 6; + + byte VALUE25 = 9; + + short VALUE26 = -32768; + + short ISTORE_0 = 59; + + short VALUE27 = 183; + + short PUTFIELD_QUICK_W = 228; + + short ICONST_4 = 7; + + short ACC_ANNOTATION = 8192; + + short ISHR = 122; + + short IRETURN = 172; + + int COUNT6 = 0; + + short VALUE28 = 45; + + short MULTIANEWARRAY = 197; + + short VALUE29 = 12; + + short GETFIELD_QUICK = 206; + + short LSHR = 123; + + short ASTORE_0 = 75; + + int COUNT7 = 254; + + int COUNT8 = 250; + + short PUTSTATIC2_QUICK = 213; + + short GETSTATIC = 178; + + short GETSTATIC_QUICK = 210; + + short L2D = 138; + + byte VALUE30 = 14; + + short SWITCH = 4712; + + short VALUE31 = 64; + + byte ATTR_UNKNOWN = -1; + + int COUNT9 = 64; + + byte VALUE32 = 23; + + short VALUE33 = 49; + + short PUTFIELD = 181; + + short GETSTATIC2_QUICK = 212; + + short VALUE34 = 2; + + byte VALUE35 = 12; + + short DASTORE = 82; + + short ALOAD_2 = 44; + + short INSTANCEOF_QUICK = 225; + + short DSUB = 103; + + short LLOAD = 22; + + byte VALUE36 = 1; + + short WIDE = 196; + + int COUNT10 = 65535; + + short LREM = 113; + + short VALUE37 = 8; + + short DSTORE_3 = 74; + + byte VALUE38 = 16; + + short NEWARRAY = 188; + + byte VALUE39 = 5; + + byte VALUE40 = 1; + + short ILOAD_0 = 26; + + short IF_ICMPGE = 162; + + short DCONST_1 = 15; + + short FDIV = 110; + + short DUP_X2 = 91; + + short LLOAD_0 = 30; + + byte VALUE41 = 15; + + short VALUE42 = 1; + + byte VALUE43 = 4; + + short ISTORE_2 = 61; + + short VALUE44 = 4; + + short BASTORE = 84; + + short ILOAD_3 = 29; + + short FLOAD_0 = 34; + + byte VALUE45 = 7; + + short VALUE46 = 146; + + short IF_ACMPNE = 166; + + byte VALUE47 = 7; + + int COUNT11 = 255; + + short VALUE48 = 52; + + short VALUE49 = 48; + + short DMUL = 107; + + short FLOAD_3 = 37; + + short IUSHR = 124; + + byte VALUE50 = 2; + + byte VALUE51 = 16; + + short IFLE = 158; + + byte VALUE52 = 9; + + short VALUE53 = 147; + + short ICONST_2 = 5; + + short ALOAD = 25; + + short FSTORE = 56; + + byte VALUE54 = 13; + + byte VALUE55 = 10; + + short ATHROW = 191; + + short FCMPL = 149; + + short DLOAD_2 = 40; + + short I2L = 133; + + short DUP = 89; + + byte VALUE56 = 13; + + short DUP2_X2 = 94; + + short CASTORE = 85; + + short LDC = 18; + + byte VALUE57 = 19; + + byte VALUE58 = 4; + + byte VALUE59 = 17; + + short INVOKESTATIC = 184; + + short ALOAD_0 = 42; + + short FCONST_2 = 13; + + short VALUE60 = 52; + + byte VALUE61 = 4; + + short SALOAD = 53; + + byte VALUE62 = 8; + + short POP2 = 88; + + short IF_ACMPEQ = 165; + + short IMPDEP2 = 255; + + byte VALUE63 = 21; + + short RET = 169; + + byte VALUE64 = 11; + + short IMPDEP1 = 254; + + short VALUE65 = 49; + + short INVOKEVIRTUALOBJECT_QUICK = 219; + + short BREAKPOINT = 202; + + short DREM = 115; + + short IF_ICMPNE = 160; + + byte VALUE66 = 16; + + short IFNULL = 198; + + short IFNONNULL = 199; + + short LDC_QUICK = 203; + + short DNEG = 119; + + short JSR = 168; + + short VALUE67 = 16384; + + short FASTORE = 81; + + short SWAP = 95; + + short VALUE68 = 16; + + short FCONST_0 = 11; + + short L2F = 137; + + byte VALUE69 = 18; + + byte VALUE70 = 12; + + short ANEWARRAY_QUICK = 222; + + short ACC_SYNTHETIC = 4096; + + short INVOKENONVIRTUAL_QUICK = 215; + + short D2I = 142; + + byte VALUE71 = 5; + + byte VALUE72 = 4; + + byte VALUE73 = 6; + + short NEW_QUICK = 221; + + short FLOAD = 23; + + short LSTORE_3 = 66; + + short PUTFIELD2_QUICK = 209; + + short DLOAD_0 = 38; + + byte VALUE74 = 5; + + short LDIV = 109; + + short INVOKESUPER_QUICK = 216; + + byte VALUE75 = 0; + + short ARETURN = 176; + + byte VALUE76 = 15; + + int COUNT12 = 248; + + short LSTORE_0 = 63; + + short IFGE = 156; + + short INVOKEVIRTUAL_QUICK_W = 226; + + short F2I = 139; + + short GOTO = 167; + + short LCMP = 148; + + short INVOKEINTERFACE = 185; + + short MULTIANEWARRAY_QUICK = 223; + + short VALUE77 = 47; + + short INVOKEVIRTUAL = 182; + + short VALUE78 = 32; + + short LOOKUPSWITCH = 171; + + short IFLT = 155; + + short SIPUSH = 17; + + byte VALUE79 = 20; + + short VALUE80 = 51; + + short VALUE81 = 128; + + byte VALUE82 = 8; + + short LLOAD_3 = 33; + + short LCONST_0 = 9; + + int COUNT13 = 127; + + short INVOKEDYNAMIC = 186; + + short LAND = 127; + + short VALUE83 = 50; + + short VALUE84 = 16; + + int MAX_CODE_SIZE = 65536; + + byte VALUE85 = 3; + + short LXOR = 131; + + short VALUE86 = 3; + + short LSUB = 101; + + short GETFIELD_QUICK_W = 227; + + short AASTORE = 83; + + byte VALUE87 = 2; + + short ANEWARRAY = 189; + + short LOR = 129; + + short VALUE88 = 24; + + short IF_ICMPLE = 164; + + short VALUE89 = 147; + + short IMUL = 104; + + byte VALUE90 = 14; + + short L2I = 136; + + short VALUE91 = 145; + + short VALUE92 = 0; + + short CHECKCAST_QUICK = 224; + + short I2D = 135; + + short ISTORE_3 = 62; + + byte VALUE93 = 0; + + short FCMPG = 150; + + short LSHL = 121; + + short GOTO_W = 200; + + int COUNT14 = 65535; + + short IAND = 126; + + short ACC_STRICT = 2048; + + short VALUE94 = 0; + + byte VALUE95 = 5; + + byte VALUE96 = 22; + + short DSTORE_1 = 72; + + byte VALUE97 = 7; + + short ISHL = 120; + + short VALUE98 = 64; + + short NEW = 187; + + short LLOAD_1 = 31; + + short DSTORE = 57; + + short IF_ICMPEQ = 159; + + short IFGT = 157; + + short DRETURN = 175; + + short INVOKEVIRTUAL_QUICK = 214; + + short IDIV = 108; + + short ASTORE_1 = 76; + + byte VALUE99 = 7; + + short MONITORENTER = 194; + + short FREM = 114; + + short VALUE100 = 8; + + short VALUE101 = 50; + + short LRETURN = 173; + + short FSTORE_1 = 68; + + short VALUE102 = 32; + + short VALUE103 = 48; + + short IASTORE = 79; + + short VALUE104 = 47; + + short LADD = 97; + + short ISTORE = 54; + + short ILOAD_2 = 28; + + short VALUE105 = 64; + + short D2L = 143; + + short VALUE106 = 1; + + byte VALUE107 = 6; + + short FLOAD_1 = 35; + + short VALUE108 = 145; + + byte VALUE109 = 15; + + short ACC_INTERFACE = 512; + + short ARRAYLENGTH = 190; + + short PUTFIELD_QUICK = 207; + + short IF_ICMPLT = 161; + + short FRETURN = 174; + + short VALUE110 = 45; + + short VALUE111 = 32; + + short VALUE112 = 46; + + short VALUE113 = 183; + + short DSTORE_0 = 71; + + short ASTORE_2 = 77; + + short JSR_W = 201; + + short INVOKESTATIC_QUICK = 217; + + short DCONST_0 = 14; + + short VALUE114 = 4; + + short IFEQ = 153; + + short ASTORE = 58; + + short VALUE115 = 0; + + short VALUE116 = 146; + + short LDC2_W = 20; + + short INVOKEINTERFACE_QUICK = 218; + + byte VALUE117 = 8; + + short DLOAD_3 = 41; + + short CHECKCAST = 192; + + short POP = 87; + + short F2L = 140; + + short DUP2 = 92; + + short IINC = 132; + + short D2F = 144; + + short UNDEFINED = -1; + + byte VALUE118 = 12; + + short LDC2_W_QUICK = 205; + + short VALUE119 = 0; + + short VALUE120 = 51; + + short IXOR = 130; + + short LNEG = 117; + + short VALUE121 = 0; + + byte VALUE122 = 10; + + short SASTORE = 86; + + short VALUE123 = 24; + + short IF_ICMPGT = 163; +} diff --git a/src/main/java/com/allatori/lib/bcel/ExceptionConstants.java b/src/main/java/com/allatori/lib/bcel/ExceptionConstants.java new file mode 100644 index 0000000..7d5c150 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/ExceptionConstants.java @@ -0,0 +1,56 @@ +package com.allatori.lib.bcel; + +public interface ExceptionConstants { + + Class TYPE10 = Throwable.class; + + Class TYPE20 = RuntimeException.class; + + Class TYPE13 = LinkageError.class; + + Class TYPE16 = ClassCircularityError.class; + + Class TYPE17 = ClassFormatError.class; + + Class TYPE4 = ExceptionInInitializerError.class; + + Class TYPE9 = IncompatibleClassChangeError.class; + + Class TYPE14 = AbstractMethodError.class; + + Class TYPE7 = IllegalAccessError.class; + + Class TYPE2 = InstantiationError.class; + + Class TYPE8 = NoSuchFieldError.class; + + Class TYPE5 = NoSuchMethodError.class; + + Class TYPE21 = NoClassDefFoundError.class; + + Class TYPE6 = UnsatisfiedLinkError.class; + + Class TYPE12 = VerifyError.class; + + Class TYPE3 = NullPointerException.class; + + Class TYPE15 = ArrayIndexOutOfBoundsException.class; + + Class TYPE18 = ArithmeticException.class; + + Class TYPE11 = NegativeArraySizeException.class; + + Class TYPE = ClassCastException.class; + + Class TYPE19 = IllegalMonitorStateException.class; + + Class[] TYPES5 = new Class[] {TYPE21, TYPE17, TYPE12, TYPE14, TYPE4, TYPE7}; + + Class[] TYPES2 = new Class[] {ExceptionConstants.TYPE8, ExceptionConstants.TYPE7, TYPE5}; + + Class[] TYPES4 = new Class[0]; + + Class[] TYPES = new Class[0]; + + Class[] TYPES3 = new Class[] {TYPE3, ExceptionConstants.TYPE15}; +} diff --git a/src/main/java/com/allatori/lib/bcel/Repository.java b/src/main/java/com/allatori/lib/bcel/Repository.java new file mode 100644 index 0000000..e63d8d1 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/Repository.java @@ -0,0 +1,110 @@ +package com.allatori.lib.bcel; + +import com.allatori.lib.bcel.classfile.JavaClass; +import com.allatori.lib.bcel.util.ClassPath; +import com.allatori.lib.bcel.util.ClassPath$ClassFile; +import com.allatori.lib.bcel.util.SyntheticRepository; +import java.io.IOException; + +public abstract class Repository { + + public static com.allatori.lib.bcel.util.Repository _repository = + SyntheticRepository.getInstance(); + + public static JavaClass[] getJavaClasss(String text) throws ClassNotFoundException { + return getJavaClasss2(lookupClass(text)); + } + + public static void clearCache() { + _repository.clear(); + } + + public static ClassPath$ClassFile lookupClassFile(String text) { + try { + ClassPath classPath; + return (classPath = _repository.getClassPath()) == null ? null : classPath.getClassFile(text); + } catch (IOException oException) { + return null; + } + } + + public static JavaClass[] getJavaClasss2(String text) throws ClassNotFoundException { + return getJavaClasss(lookupClass(text)); + } + + public static void removeClass(JavaClass javaClass) { + _repository.processJavaClass2(javaClass); + } + + public static boolean matchesJavaClass(String text, JavaClass javaClass) + throws ClassNotFoundException { + return matchesJavaClass2(lookupClass(text), javaClass); + } + + public static void setRepository(com.allatori.lib.bcel.util.Repository repository) { + _repository = repository; + } + + public static JavaClass addClass(JavaClass javaClass) { + JavaClass javaClass2 = _repository.getJavaClass(javaClass.getText2()); + _repository.processJavaClass(javaClass); + return javaClass2; + } + + public static boolean matchesJavaClass2(String text, JavaClass javaClass) + throws ClassNotFoundException { + return matchesJavaClass(lookupClass(text), javaClass); + } + + public static JavaClass[] getJavaClasss(JavaClass javaClass) throws ClassNotFoundException { + return javaClass.createJavaClasss2(); + } + + public static com.allatori.lib.bcel.util.Repository getRepository() { + return _repository; + } + + public static JavaClass[] getJavaClasss2(JavaClass javaClass) throws ClassNotFoundException { + return javaClass.createJavaClasss(); + } + + public static boolean matchesText(String text, String text2) throws ClassNotFoundException { + return matchesJavaClass(lookupClass(text), lookupClass(text2)); + } + + public static boolean matchesJavaClass(JavaClass javaClass, JavaClass javaClass2) + throws ClassNotFoundException { + return javaClass.matchesJavaClass2(javaClass2); + } + + public static JavaClass lookupClass(Class classValue) throws ClassNotFoundException { + return _repository.loadClass(classValue); + } + + public static boolean matchesJavaClass2(JavaClass javaClass, JavaClass javaClass2) + throws ClassNotFoundException { + return javaClass.matchesJavaClass(javaClass2); + } + + public static boolean matchesText2(String text, String text2) throws ClassNotFoundException { + return matchesJavaClass2(lookupClass(text), lookupClass(text2)); + } + + public static void removeClass(String text) { + _repository.processJavaClass2(_repository.getJavaClass(text)); + } + + public static boolean matchesText(JavaClass javaClass, String text) + throws ClassNotFoundException { + return matchesJavaClass(javaClass, lookupClass(text)); + } + + public static boolean matchesText2(JavaClass javaClass, String text) + throws ClassNotFoundException { + return matchesJavaClass2(javaClass, lookupClass(text)); + } + + public static JavaClass lookupClass(String text) throws ClassNotFoundException { + return _repository.getJavaClass2(text); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/AccessFlags.java b/src/main/java/com/allatori/lib/bcel/classfile/AccessFlags.java new file mode 100644 index 0000000..dbc41b8 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/AccessFlags.java @@ -0,0 +1,162 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.Serializable; + +public abstract class AccessFlags implements Serializable { + + public int access_flags; + + public final void processEnabled(boolean matches) { + this.setFlag(256, matches); + } + + public final void processEnabled2(boolean matches) { + this.setFlag(16, matches); + } + + public final void processEnabled3(boolean matches) { + this.setFlag(1024, matches); + } + + public final boolean isEnabled() { + return (this.access_flags & 64) != 0; + } + + public final int getAccess_flags() { + return this.access_flags; + } + + public final boolean isEnabled2() { + return (this.access_flags & 8192) != 0; + } + + public final void setAccess_flags(int access_flags) { + this.access_flags = access_flags; + } + + public final boolean isEnabled3() { + return (this.access_flags & 16) != 0; + } + + public final void processCount(int value) { + this.setAccess_flags(value); + } + + public final void processEnabled4(boolean matches) { + this.setFlag(8, matches); + } + + public final void processEnabled5(boolean matches) { + this.setFlag(2, matches); + } + + public AccessFlags(int access_flags) { + super(); + this.access_flags = access_flags; + } + + public final void processEnabled6(boolean matches) { + this.setFlag(128, matches); + } + + public final void processEnabled7(boolean matches) { + this.setFlag(4, matches); + } + + public final void processEnabled8(boolean matches) { + this.setFlag(2048, matches); + } + + public final boolean isEnabled4() { + return (this.access_flags & 128) != 0; + } + + public final boolean isEnabled5() { + return (this.access_flags & 512) != 0; + } + + public final boolean isEnabled6() { + return (this.access_flags & 1) != 0; + } + + public final boolean isEnabled7() { + return (this.access_flags & 2048) != 0; + } + + public final int getAccess_flags2() { + return this.access_flags; + } + + public final void setFlag(int access_flags, boolean matches) { + if ((this.access_flags & access_flags) != 0) { + if (!matches) { + this.access_flags ^= access_flags; + return; + } + } else if (matches) { + this.access_flags |= access_flags; + } + } + + public final boolean isEnabled8() { + return (this.access_flags & 4096) != 0; + } + + public final void processEnabled9(boolean matches) { + this.setFlag(4096, matches); + } + + public final void processEnabled10(boolean matches) { + this.setFlag(8192, matches); + } + + public final boolean isEnabled9() { + return (this.access_flags & 2) != 0; + } + + public final void processEnabled11(boolean matches) { + this.setFlag(512, matches); + } + + public final void processEnabled12(boolean matches) { + this.setFlag(32, matches); + } + + public final void processEnabled13(boolean matches) { + this.setFlag(1, matches); + } + + public final boolean isEnabled10() { + return (this.access_flags & 16384) != 0; + } + + public final void processEnabled14(boolean matches) { + this.setFlag(16384, matches); + } + + public final void processEnabled15(boolean matches) { + this.setFlag(64, matches); + } + + public final boolean isEnabled11() { + return (this.access_flags & 8) != 0; + } + + public AccessFlags() {} + + public final boolean isEnabled12() { + return (this.access_flags & 32) != 0; + } + + public final boolean isEnabled13() { + return (this.access_flags & 4) != 0; + } + + public final boolean isEnabled14() { + return (this.access_flags & 256) != 0; + } + + public final boolean isEnabled15() { + return (this.access_flags & 1024) != 0; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/AnnotationDefault.java b/src/main/java/com/allatori/lib/bcel/classfile/AnnotationDefault.java new file mode 100644 index 0000000..05563e9 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/AnnotationDefault.java @@ -0,0 +1,45 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public class AnnotationDefault extends Attribute { + + public ElementValue default_value; + + public AnnotationDefault( + int value, int value2, ElementValue elementValue, ConstantPool constantPool) { + super((byte) 16, value, value2, constantPool); + this.setDefaultValue(elementValue); + } + + @Override + public Attribute copy(ConstantPool constantPool) { + throw new RuntimeException("Not implemented yet!"); + } + + @Override + public void accept(Visitor visitor) {} + + @Override + public void dump(DataOutputStream dataOutputStream) throws IOException { + super.dump(dataOutputStream); + this.default_value.dump(dataOutputStream); + } + + public final void setDefaultValue(ElementValue elementValue) { + this.default_value = elementValue; + } + + public AnnotationDefault( + int value, int value2, DataInputStream dataInputStream, ConstantPool constantPool) + throws IOException { + this(value, value2, (ElementValue) null, constantPool); + this.default_value = ElementValue.createElementValue(dataInputStream, constantPool); + } + + public final ElementValue getDefaultValue() { + return this.default_value; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/AnnotationElementValue.java b/src/main/java/com/allatori/lib/bcel/classfile/AnnotationElementValue.java new file mode 100644 index 0000000..f84f397 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/AnnotationElementValue.java @@ -0,0 +1,36 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataOutputStream; +import java.io.IOException; + +public class AnnotationElementValue extends ElementValue { + + public AnnotationEntry annotationEntry; + + @Override + public String getText() { + StringBuffer stringBuffer = new StringBuffer(); + stringBuffer.append(this.annotationEntry.toString()); + return stringBuffer.toString(); + } + + public AnnotationEntry getAnnotationEntry() { + return this.annotationEntry; + } + + public AnnotationElementValue( + int value, AnnotationEntry annotationEntry2, ConstantPool constantPool) { + super(value, constantPool); + if (value != 64) { + throw new RuntimeException( + "Only element values of type annotation can be built with this ctor"); + } + this.annotationEntry = annotationEntry2; + } + + @Override + public void dump(DataOutputStream dataOutputStream) throws IOException { + dataOutputStream.writeByte(this.type); + this.annotationEntry.dump(dataOutputStream); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/AnnotationEntry.java b/src/main/java/com/allatori/lib/bcel/classfile/AnnotationEntry.java new file mode 100644 index 0000000..e3fc0da --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/AnnotationEntry.java @@ -0,0 +1,106 @@ +package com.allatori.lib.bcel.classfile; + +import com.allatori.lib.bcel.Constants; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public class AnnotationEntry implements Node, Constants { + + public List element_value_pairs; + + public ConstantPool constant_pool; + + public int count; + + public int count2; + + public boolean isRuntimeVisible; + + public ElementValuePair[] getElementValuePairs() { + return (ElementValuePair[]) + this.element_value_pairs.toArray(new ElementValuePair[this.element_value_pairs.size()]); + } + + public void dump(DataOutputStream dataOutputStream) throws IOException { + int value = 0; + dataOutputStream.writeShort(this.count2); + dataOutputStream.writeShort(this.element_value_pairs.size()); + for (int index = 0; value < this.element_value_pairs.size(); value = index) { + Object result = this.element_value_pairs.get(index); + index++; + ((ElementValuePair) result).dump(dataOutputStream); + } + } + + public String getText() { + return ((ConstantUtf8) this.constant_pool.getConstant(this.count2, (byte) 1)).getBytes(); + } + + public int getCount2() { + return this.count2; + } + + public static AnnotationEntry createAnnotationEntry( + DataInputStream dataInputStream, ConstantPool constantPool, boolean matches) + throws IOException { + AnnotationEntry annotationEntry = + new AnnotationEntry(dataInputStream.readUnsignedShort(), constantPool, matches); + int value = 0; + annotationEntry.count = dataInputStream.readUnsignedShort(); + for (int index = 0; value < annotationEntry.count; value = index) { + List values = annotationEntry.element_value_pairs; + int value2 = dataInputStream.readUnsignedShort(); + ElementValue elementValue = ElementValue.createElementValue(dataInputStream, constantPool); + index++; + values.add(new ElementValuePair(value2, elementValue, constantPool)); + } + return annotationEntry; + } + + public String createText() { + StringBuffer stringBuffer; + (stringBuffer = new StringBuffer()).append("@"); + stringBuffer.append(this.getText()); + if (this.getElementValuePairs().length > 0) { + stringBuffer.append("("); + int value = 0; + for (int value2 = value; value2 < this.getElementValuePairs().length; value2 = value) { + ElementValuePair elementValuePair = this.getElementValuePairs()[value]; + StringBuffer stringBuffer2 = stringBuffer; + value++; + stringBuffer2.append(elementValuePair.createText()); + } + stringBuffer.append(")"); + } + return stringBuffer.toString(); + } + + public void addElementNameValuePair(ElementValuePair elementValuePair) { + if (this.element_value_pairs == null) { + this.element_value_pairs = new ArrayList(); + } + this.element_value_pairs.add(elementValuePair); + } + + public AnnotationEntry(int count2, ConstantPool constantPool, boolean isRuntimeVisible) { + super(); + this.count2 = count2; + this.constant_pool = constantPool; + this.isRuntimeVisible = isRuntimeVisible; + this.element_value_pairs = new ArrayList(); + } + + @Override + public void accept(Visitor visitor) {} + + public final int getCount() { + return this.count; + } + + public boolean isRuntimeVisible() { + return this.isRuntimeVisible; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/Annotations.java b/src/main/java/com/allatori/lib/bcel/classfile/Annotations.java new file mode 100644 index 0000000..9741a1d --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/Annotations.java @@ -0,0 +1,81 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public abstract class Annotations extends Attribute { + + public int count; + + public AnnotationEntry[] annotation_table; + + public boolean isRuntimeVisible; + + public boolean isRuntimeVisible() { + return this.isRuntimeVisible; + } + + public Annotations( + byte value, + int value2, + int value3, + DataInputStream dataInputStream, + ConstantPool constantPool, + boolean matches) + throws IOException { + this(value, value2, value3, (AnnotationEntry[]) null, constantPool, matches); + this.count = dataInputStream.readUnsignedShort(); + this.annotation_table = new AnnotationEntry[this.count]; + int value4; + for (int value5 = value4 = 0; value5 < this.count; value5 = value4) { + AnnotationEntry[] annotationEntrys = this.annotation_table; + AnnotationEntry annotationEntry = + AnnotationEntry.createAnnotationEntry(dataInputStream, constantPool, matches); + int value6 = value4; + value4++; + annotationEntrys[value6] = annotationEntry; + } + } + + public void writeAnnotations(DataOutputStream dataOutputStream) throws IOException { + int value = 0; + dataOutputStream.writeShort(this.count); + for (int index = 0; value < this.count; value = index) { + int value2 = index; + AnnotationEntry[] annotationEntrys = this.annotation_table; + index++; + annotationEntrys[value2].dump(dataOutputStream); + } + } + + public AnnotationEntry[] getAnnotationEntries() { + return this.annotation_table; + } + + public final void setAnnotationTable(AnnotationEntry[] annotationEntrys) { + this.annotation_table = annotationEntrys; + this.count = annotationEntrys == null ? 0 : annotationEntrys.length; + } + + public final int getNumAnnotations() { + return this.count; + } + + @Override + public void accept(Visitor visitor) { + visitor.visitAnnotation(this); + } + + public Annotations( + byte value, + int value2, + int value3, + AnnotationEntry[] annotationEntrys, + ConstantPool constantPool, + boolean isRuntimeVisible) { + super(value, value2, value3, constantPool); + this.setAnnotationTable(annotationEntrys); + this.isRuntimeVisible = isRuntimeVisible; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/ArrayElementValue.java b/src/main/java/com/allatori/lib/bcel/classfile/ArrayElementValue.java new file mode 100644 index 0000000..1dc11e8 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/ArrayElementValue.java @@ -0,0 +1,53 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataOutputStream; +import java.io.IOException; + +public class ArrayElementValue extends ElementValue { + + public ElementValue[] evalues; + + public ElementValue[] getElementValuesArray() { + return this.evalues; + } + + public int getElementValuesArraySize() { + return this.evalues.length; + } + + @Override + public String getText() { + StringBuffer stringBuffer; + (stringBuffer = new StringBuffer()).append("["); + int value = 0; + for (int value2 = value; value2 < this.evalues.length; value2 = ++value) { + stringBuffer.append(this.evalues[value].getText()); + if (value + 1 < this.evalues.length) { + stringBuffer.append(","); + } + } + stringBuffer.append("]"); + return stringBuffer.toString(); + } + + public ArrayElementValue(int value, ElementValue[] elementValues, ConstantPool constantPool) { + super(value, constantPool); + if (value != 91) { + throw new RuntimeException("Only element values of type array can be built with this ctor"); + } + this.evalues = elementValues; + } + + @Override + public void dump(DataOutputStream dataOutputStream) throws IOException { + dataOutputStream.writeByte(this.type); + dataOutputStream.writeShort(this.evalues.length); + int value; + for (int value2 = value = 0; value2 < this.evalues.length; value2 = value) { + int value3 = value; + ElementValue[] elementValues = this.evalues; + value++; + elementValues[value3].dump(dataOutputStream); + } + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/Attribute.java b/src/main/java/com/allatori/lib/bcel/classfile/Attribute.java new file mode 100644 index 0000000..e1cea64 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/Attribute.java @@ -0,0 +1,175 @@ +package com.allatori.lib.bcel.classfile; + +import com.allatori.lib.bcel.Constants; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +public abstract class Attribute implements Cloneable, Node, Serializable { + + public static Map readers = new HashMap(); + + public ConstantPool constant_pool; + + public int length; + + public byte tag; + + public int name_index; + + public final byte getTag() { + return this.tag; + } + + public Attribute(byte tag, int name_index, int length, ConstantPool constantPool) { + super(); + this.tag = tag; + this.name_index = name_index; + this.length = length; + this.constant_pool = constantPool; + } + + @Override + public Object clone() { + try { + return super.clone(); + } catch (CloneNotSupportedException cloneNotSupportedException) { + cloneNotSupportedException.printStackTrace(); + return (Object) null; + } + } + + public static void addAttributeReader(String text, AttributeReader attributeReader) { + readers.put(text, attributeReader); + } + + public final void setConstantPool(ConstantPool constantPool) { + this.constant_pool = constantPool; + } + + public final int getName_index() { + return this.name_index; + } + + public final int getLength() { + return this.length; + } + + public final void setName_index(int name_index) { + this.name_index = name_index; + } + + public final ConstantPool getConstantPool() { + return this.constant_pool; + } + + public static void removeAttributeReader(String text) { + readers.remove(text); + } + + public static final Attribute readAttribute( + DataInputStream dataInputStream, ConstantPool constantPool) throws IOException { + byte value = -1; + int value2; + String bytes = + ((ConstantUtf8) + constantPool.getConstant(value2 = dataInputStream.readUnsignedShort(), (byte) 1)) + .getBytes(); + int value3 = dataInputStream.readInt(); + byte value4; + byte value5 = value4 = 0; + while (true) { + if (value5 >= 24) { + value5 = value; + break; + } + if (bytes.equals(Constants.TEXTS4[value4])) { + value5 = value4; + break; + } + value5 = ++value4; + } + switch (value5) { + case -1: + AttributeReader attributeReader; + if ((attributeReader = (AttributeReader) readers.get(bytes)) != null) { + return attributeReader.createAttribute(value2, value3, dataInputStream, constantPool); + } + return new Unknown(value2, value3, dataInputStream, constantPool); + case 0: + return new SourceFile(value2, value3, dataInputStream, constantPool); + case 1: + return new ConstantValue(value2, value3, dataInputStream, constantPool); + case 2: + return new Code(value2, value3, dataInputStream, constantPool); + case 3: + return new ExceptionTable(value2, value3, dataInputStream, constantPool); + case 4: + return new LineNumberTable(value2, value3, dataInputStream, constantPool); + case 5: + return new LocalVariableTable(value2, value3, dataInputStream, constantPool); + case 6: + return new InnerClasses(value2, value3, dataInputStream, constantPool); + case 7: + return new Synthetic(value2, value3, dataInputStream, constantPool); + case 8: + return new Deprecated(value2, value3, dataInputStream, constantPool); + case 9: + return new PMGClass(value2, value3, dataInputStream, constantPool); + case 10: + return new Signature(value2, value3, dataInputStream, constantPool); + case 11: + return new StackMap(value2, value3, dataInputStream, constantPool); + case 12: + return new RuntimeVisibleAnnotations(value2, value3, dataInputStream, constantPool); + case 13: + return new RuntimeInvisibleAnnotations(value2, value3, dataInputStream, constantPool); + case 14: + return new RuntimeVisibleParameterAnnotations( + value2, value3, dataInputStream, constantPool); + case 15: + return new RuntimeInvisibleParameterAnnotations( + value2, value3, dataInputStream, constantPool); + case 16: + return new AnnotationDefault(value2, value3, dataInputStream, constantPool); + case 17: + return new Unknown(value2, value3, dataInputStream, constantPool); + case 18: + return new EnclosingMethod(value2, value3, dataInputStream, constantPool); + case 19: + return new Unknown(value2, value3, dataInputStream, constantPool); + case 20: + return new BootstrapMethods(value2, value3, dataInputStream, constantPool); + case 21: + return new MethodParameters(value2, value3, dataInputStream, constantPool); + case 22: + return new NestHost(value2, value3, dataInputStream, constantPool); + case 23: + return new NestMembers(value2, value3, dataInputStream, constantPool); + default: + throw new IllegalStateException("Ooops! default case reached."); + } + } + + public final void setLength(int length) { + this.length = length; + } + + @Override + public abstract void accept(Visitor visitor); + + public abstract Attribute copy(ConstantPool constantPool); + + @Override + public String toString() { + return ((ConstantUtf8) this.constant_pool.getConstant(this.name_index, (byte) 1)).getBytes(); + } + + public void dump(DataOutputStream dataOutputStream) throws IOException { + dataOutputStream.writeShort(this.name_index); + dataOutputStream.writeInt(this.length); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/AttributeReader.java b/src/main/java/com/allatori/lib/bcel/classfile/AttributeReader.java new file mode 100644 index 0000000..4b949c5 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/AttributeReader.java @@ -0,0 +1,9 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInputStream; + +public interface AttributeReader { + + Attribute createAttribute( + int value, int value2, DataInputStream dataInputStream, ConstantPool constantPool); +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/BootstrapMethod.java b/src/main/java/com/allatori/lib/bcel/classfile/BootstrapMethod.java new file mode 100644 index 0000000..f350d5c --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/BootstrapMethod.java @@ -0,0 +1,66 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.Serializable; + +public class BootstrapMethod implements Serializable, Cloneable { + + public int[] bootstrap_arguments; + + public int bootstrap_method_ref; + + public final void dump(DataOutputStream dataOutputStream) throws IOException { + dataOutputStream.writeShort(this.bootstrap_method_ref); + dataOutputStream.writeShort(this.bootstrap_arguments.length); + int[] values = this.bootstrap_arguments; + int value = this.bootstrap_arguments.length; + int value2; + for (int value3 = value2 = 0; value3 < value; value3 = value2) { + int value4 = value2; + value2++; + dataOutputStream.writeShort(values[value4]); + } + } + + public BootstrapMethod() {} + + public BootstrapMethod(DataInputStream dataInputStream) throws IOException { + this.bootstrap_method_ref = dataInputStream.readUnsignedShort(); + int value; + this.bootstrap_arguments = new int[value = dataInputStream.readUnsignedShort()]; + int value2; + for (int value3 = value2 = 0; value3 < value; value3 = value2) { + int[] values = this.bootstrap_arguments; + int value4 = dataInputStream.readUnsignedShort(); + int value5 = value2; + value2++; + values[value5] = value4; + } + } + + public int getBootstrap_method_ref() { + return this.bootstrap_method_ref; + } + + public void setBootstrapArguments(int[] bootstrap_arguments) { + this.bootstrap_arguments = bootstrap_arguments; + } + + public void setBootstrapMethodRef(int bootstrap_method_ref) { + this.bootstrap_method_ref = bootstrap_method_ref; + } + + public int[] getBootstrapArguments() { + return this.bootstrap_arguments; + } + + public BootstrapMethod copy() { + try { + return (BootstrapMethod) this.clone(); + } catch (CloneNotSupportedException cloneNotSupportedException) { + return null; + } + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/BootstrapMethods.java b/src/main/java/com/allatori/lib/bcel/classfile/BootstrapMethods.java new file mode 100644 index 0000000..83c67e5 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/BootstrapMethods.java @@ -0,0 +1,73 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public class BootstrapMethods extends Attribute { + + public BootstrapMethod[] bootstrap_methods; + + @Override + public final void dump(DataOutputStream dataOutputStream) throws IOException { + super.dump(dataOutputStream); + dataOutputStream.writeShort(this.bootstrap_methods.length); + BootstrapMethod[] bootstrapMethods = this.bootstrap_methods; + int value = this.bootstrap_methods.length; + int value2; + for (int value3 = value2 = 0; value3 < value; value3 = value2) { + int value4 = value2; + value2++; + bootstrapMethods[value4].dump(dataOutputStream); + } + } + + public final BootstrapMethod[] getBootstrapMethods() { + return this.bootstrap_methods; + } + + public BootstrapMethods( + int value, int value2, BootstrapMethod[] bootstrapMethods, ConstantPool constantPool) { + super((byte) 20, value, value2, constantPool); + this.bootstrap_methods = bootstrapMethods; + } + + @Override + public void accept(Visitor visitor) {} + + public final void setBootstrapMethods(BootstrapMethod[] bootstrapMethods) { + this.bootstrap_methods = bootstrapMethods; + } + + public BootstrapMethods( + int value, int value2, DataInputStream dataInputStream, ConstantPool constantPool) + throws IOException { + this(value, value2, (BootstrapMethod[]) null, constantPool); + int value3; + this.bootstrap_methods = new BootstrapMethod[value3 = dataInputStream.readUnsignedShort()]; + int value4; + for (int value5 = value4 = 0; value5 < value3; value5 = value4) { + BootstrapMethod[] bootstrapMethods = this.bootstrap_methods; + BootstrapMethod bootstrapMethod = new BootstrapMethod(dataInputStream); + int value6 = value4; + value4++; + bootstrapMethods[value6] = bootstrapMethod; + } + } + + public BootstrapMethods copy(ConstantPool constantPool) { + BootstrapMethods bootstrapMethods; + (bootstrapMethods = (BootstrapMethods) this.clone()).bootstrap_methods = + new BootstrapMethod[this.bootstrap_methods.length]; + int value; + for (int value2 = value = 0; value2 < this.bootstrap_methods.length; value2 = value) { + BootstrapMethod[] bootstrapMethods2 = bootstrapMethods.bootstrap_methods; + int value3 = value; + BootstrapMethod bootstrapMethod = this.bootstrap_methods[value].copy(); + value++; + bootstrapMethods2[value3] = bootstrapMethod; + } + bootstrapMethods.constant_pool = constantPool; + return bootstrapMethods; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/ClassElementValue.java b/src/main/java/com/allatori/lib/bcel/classfile/ClassElementValue.java new file mode 100644 index 0000000..613cbb3 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/ClassElementValue.java @@ -0,0 +1,33 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataOutputStream; +import java.io.IOException; + +public class ClassElementValue extends ElementValue { + + public int idx; + + public String getText2() { + return ((ConstantUtf8) this.cpool.getConstant(this.idx, (byte) 1)).getBytes(); + } + + public ClassElementValue(int value, int idx, ConstantPool constantPool) { + super(value, constantPool); + this.idx = idx; + } + + @Override + public void dump(DataOutputStream dataOutputStream) throws IOException { + dataOutputStream.writeByte(this.type); + dataOutputStream.writeShort(this.idx); + } + + public int getIndex() { + return this.idx; + } + + @Override + public String getText() { + return ((ConstantUtf8) this.cpool.getConstant(this.idx, (byte) 1)).getBytes(); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/ClassFormatException.java b/src/main/java/com/allatori/lib/bcel/classfile/ClassFormatException.java new file mode 100644 index 0000000..c168db7 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/ClassFormatException.java @@ -0,0 +1,14 @@ +package com.allatori.lib.bcel.classfile; + +public class ClassFormatException extends RuntimeException { + + public ClassFormatException() {} + + public ClassFormatException(String text, Throwable throwable) { + super(text, throwable); + } + + public ClassFormatException(String text) { + super(text); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/ClassParser.java b/src/main/java/com/allatori/lib/bcel/classfile/ClassParser.java new file mode 100644 index 0000000..94fe781 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/ClassParser.java @@ -0,0 +1,205 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.BufferedInputStream; +import java.io.DataInputStream; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +public final class ClassParser { + + public int count; + + public int count2; + + public Method[] methods; + + public String zip_file; + + public int count3; + + public boolean fileOwned; + + public DataInputStream file; + + public Field[] fields; + + public String file_name; + + public int count4; + + public static final int BUFSIZE = 8192; + + public boolean is_zip; + + public Attribute[] attributes; + + public int[] interfaces; + + public int count5; + + public ConstantPool constant_pool; + + public final void readInterfaces() throws IOException, ClassFormatException { + int value; + this.interfaces = new int[value = this.file.readUnsignedShort()]; + int value2; + for (int value3 = value2 = 0; value3 < value; value3 = value2) { + int[] values = this.interfaces; + int value4 = this.file.readUnsignedShort(); + int value5 = value2; + value2++; + values[value5] = value4; + } + } + + public final void readID() throws IOException, ClassFormatException { + int value = -889275714; + if (this.file.readInt() != value) { + throw new ClassFormatException(("" + this.file_name + " is not a Java .class file")); + } + } + + public final void readFields() throws IOException, ClassFormatException { + int value; + this.fields = new Field[value = this.file.readUnsignedShort()]; + int value2; + for (int value3 = value2 = 0; value3 < value; value3 = value2) { + Field[] fields2 = this.fields; + Field field = new Field(this.file, this.constant_pool); + int value4 = value2; + value2++; + fields2[value4] = field; + } + } + + public final void readClassInfo() throws IOException, ClassFormatException { + this.count5 = this.file.readUnsignedShort(); + if ((this.count5 & 512) != 0) { + this.count5 |= 1024; + } + if ((this.count5 & 1024) != 0 && (this.count5 & 16) != 0) { + throw new ClassFormatException("Class can't be both final and abstract"); + } + this.count = this.file.readUnsignedShort(); + this.count2 = this.file.readUnsignedShort(); + } + + public final void readConstantPool() throws IOException, ClassFormatException { + this.constant_pool = new ConstantPool(this.file); + } + + public JavaClass parse() throws IOException, ClassFormatException { + ZipFile zipFile = null; + try { + ClassParser classParser; + label59: + { + if (this.fileOwned) { + if (this.is_zip) { + ZipEntry entry = (zipFile = new ZipFile(this.zip_file)).getEntry(this.file_name); + classParser = this; + this.file = + new DataInputStream(new BufferedInputStream(zipFile.getInputStream(entry), 8192)); + break label59; + } + this.file = + new DataInputStream( + new BufferedInputStream(new FileInputStream(this.file_name), 8192)); + } + classParser = this; + } + classParser.readID(); + this.readVersion(); + this.readConstantPool(); + this.readClassInfo(); + this.readInterfaces(); + this.readFields(); + this.readMethods(); + this.readAttributes(); + } finally { + if (this.fileOwned) { + this.file.close(); + if (zipFile != null) { + zipFile.close(); + } + } + } + return new JavaClass( + this.count, + this.count2, + this.file_name, + this.count3, + this.count4, + this.count5, + this.constant_pool, + this.interfaces, + this.fields, + this.methods, + this.attributes, + (byte) (this.is_zip ? 3 : 2)); + } + + public ClassParser(String file_name) throws IOException { + super(); + this.is_zip = false; + this.file_name = file_name; + this.fileOwned = true; + } + + public final void readVersion() throws IOException, ClassFormatException { + this.count4 = this.file.readUnsignedShort(); + this.count3 = this.file.readUnsignedShort(); + } + + public final void readAttributes() throws IOException, ClassFormatException { + int value; + this.attributes = new Attribute[value = this.file.readUnsignedShort()]; + int value2; + for (int value3 = value2 = 0; value3 < value; value3 = value2) { + Attribute[] attributes2 = this.attributes; + Attribute attribute = Attribute.readAttribute(this.file, this.constant_pool); + int value4 = value2; + value2++; + attributes2[value4] = attribute; + } + } + + public ClassParser(InputStream inputStream, String file_name) { + super(); + this.file_name = file_name; + this.fileOwned = false; + String text2; + this.is_zip = + (text2 = inputStream.getClass().getName()).startsWith("java.util.zip.") + || text2.startsWith("java.util.jar."); + if (inputStream instanceof DataInputStream) { + this.file = (DataInputStream) inputStream; + } else { + this.file = new DataInputStream(new BufferedInputStream(inputStream, 8192)); + } + } + + public final void readMethods() throws IOException { + int value; + this.methods = new Method[value = this.file.readUnsignedShort()]; + int value2; + for (int value3 = value2 = 0; value3 < value; value3 = value2) { + Method[] methods2 = this.methods; + Method method = new Method(this.file, this.constant_pool); + int value4 = value2; + value2++; + methods2[value4] = method; + } + } + + public ClassParser(String zip_file, String file_name) { + super(); + this.is_zip = true; + this.fileOwned = true; + this.zip_file = zip_file; + this.file_name = file_name; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/Code.java b/src/main/java/com/allatori/lib/bcel/classfile/Code.java new file mode 100644 index 0000000..49f5908 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/Code.java @@ -0,0 +1,262 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public final class Code extends Attribute { + + public int max_locals; + + public Attribute[] attributes; + + public int attributes_count; + + public CodeException[] exception_table; + + public int max_stack; + + public int exception_table_length; + + public int code_length; + + public byte[] code; + + @Override + public void accept(Visitor visitor) { + visitor.visitCode(this); + } + + public final void setMax_locals(int max_locals) { + this.max_locals = max_locals; + } + + public final void setCode(byte[] code) { + this.code = code; + this.code_length = code == null ? 0 : code.length; + } + + public final byte[] getCode() { + return this.code; + } + + public Code( + int value, + int value2, + int max_stack, + int max_locals, + byte[] values, + CodeException[] codeExceptions, + Attribute[] attributes, + ConstantPool constantPool) { + super((byte) 2, value, value2, constantPool); + this.max_stack = max_stack; + this.max_locals = max_locals; + this.setCode(values); + this.setExceptionTable(codeExceptions); + this.setAttributes(attributes); + } + + public Code(int value, int length, DataInputStream dataInputStream, ConstantPool constantPool) + throws IOException { + this( + value, + length, + dataInputStream.readUnsignedShort(), + dataInputStream.readUnsignedShort(), + (byte[]) null, + (CodeException[]) null, + (Attribute[]) null, + constantPool); + this.code_length = dataInputStream.readInt(); + this.code = new byte[this.code_length]; + dataInputStream.readFully(this.code); + this.exception_table_length = dataInputStream.readUnsignedShort(); + this.exception_table = new CodeException[this.exception_table_length]; + int value3; + for (int value4 = value3 = 0; value4 < this.exception_table_length; value4 = value3) { + CodeException[] codeExceptions = this.exception_table; + CodeException codeException = new CodeException(dataInputStream); + int value5 = value3; + value3++; + codeExceptions[value5] = codeException; + } + this.attributes_count = dataInputStream.readUnsignedShort(); + this.attributes = new Attribute[this.attributes_count]; + int value6; + for (int value7 = value6 = 0; value7 < this.attributes_count; value7 = value6) { + Attribute[] attributes2 = this.attributes; + Attribute attribute = Attribute.readAttribute(dataInputStream, constantPool); + int value8 = value6; + value6++; + attributes2[value8] = attribute; + } + this.length = length; + } + + public final void setMax_stack(int max_stack) { + this.max_stack = max_stack; + } + + public final int getMax_stack() { + return this.max_stack; + } + + public final CodeException[] getExceptionTable() { + return this.exception_table; + } + + public final int calculateCount() { + return 8 + this.code_length + 2 + 8 * this.exception_table_length + 2; + } + + public LineNumberTable getLineNumberTable() { + int value; + for (int value2 = value = 0; value2 < this.attributes_count; value2 = ++value) { + if (this.attributes[value] instanceof LineNumberTable) { + return (LineNumberTable) this.attributes[value]; + } + } + return null; + } + + @Override + public Attribute copy(ConstantPool constantPool) { + Code code2 = (Code) this.clone(); + if (this.code != null) { + code2.code = new byte[this.code.length]; + System.arraycopy(this.code, 0, code2.code, 0, this.code.length); + } + code2.constant_pool = constantPool; + code2.exception_table = new CodeException[this.exception_table_length]; + int value; + for (int value2 = value = 0; value2 < this.exception_table_length; value2 = value) { + CodeException[] codeExceptions = code2.exception_table; + CodeException codeException = this.exception_table[value].copy(); + int value3 = value; + value++; + codeExceptions[value3] = codeException; + } + code2.attributes = new Attribute[this.attributes_count]; + int value4; + for (int value5 = value4 = 0; value5 < this.attributes_count; value5 = value4) { + Attribute[] attributes2 = code2.attributes; + Attribute attribute = this.attributes[value4].copy(constantPool); + int value6 = value4; + value4++; + attributes2[value6] = attribute; + } + return code2; + } + + @Override + public final void dump(DataOutputStream dataOutputStream) throws IOException { + int value = 0; + super.dump(dataOutputStream); + dataOutputStream.writeShort(this.max_stack); + dataOutputStream.writeShort(this.max_locals); + dataOutputStream.writeInt(this.code_length); + dataOutputStream.write(this.code, 0, this.code_length); + dataOutputStream.writeShort(this.exception_table_length); + for (int index = 0; value < this.exception_table_length; value = index) { + int value2 = index; + CodeException[] codeExceptions = this.exception_table; + index++; + codeExceptions[value2].dump(dataOutputStream); + } + dataOutputStream.writeShort(this.attributes_count); + int value3; + for (int value4 = value3 = 0; value4 < this.attributes_count; value4 = value3) { + int value5 = value3; + Attribute[] attributes2 = this.attributes; + value3++; + attributes2[value5].dump(dataOutputStream); + } + } + + public final Attribute[] getAttributes() { + return this.attributes; + } + + public final int calculateCount2() { + int value = 0; + int value2; + for (int value3 = value2 = 0; value3 < this.attributes_count; value3 = value2) { + int value4 = this.attributes[value2].length; + int value5 = value; + value2++; + value = value5 + value4 + (byte) 6; + } + return value + this.calculateCount(); + } + + public LocalVariableTable getLocalVariableTable() { + int value; + for (int value2 = value = 0; value2 < this.attributes_count; value2 = ++value) { + if (this.attributes[value] instanceof LocalVariableTable) { + return (LocalVariableTable) this.attributes[value]; + } + } + return null; + } + + public Code(Code code) { + this( + code.getName_index(), + code.getLength(), + code.getMax_stack(), + code.getMax_locals(), + code.getCode(), + code.getExceptionTable(), + code.getAttributes(), + code.getConstantPool()); + } + + public final void setAttributes(Attribute[] attributes2) { + this.attributes = attributes2; + this.attributes_count = attributes2 == null ? 0 : attributes2.length; + this.length = this.calculateCount2(); + } + + public final String toString(boolean matches) { + StringBuffer stringBuffer; + (stringBuffer = new StringBuffer(100)) + .append("Code(max_stack = ") + .append(this.max_stack) + .append(", max_locals = ") + .append(this.max_locals) + .append(", code_length = ") + .append(this.code_length) + .append(")\n") + .append(Utility.codeToString(this.code, this.constant_pool, 0, -1, matches)); + if (this.exception_table_length > 0) { + stringBuffer.append("\nException handler(s) = \n").append("From\tTo\tHandler\tType\n"); + int value = 0; + for (int value2 = value; value2 < this.exception_table_length; value2 = value) { + StringBuffer stringBuffer2 = + stringBuffer.append(this.exception_table[value].toString(this.constant_pool, matches)); + value++; + stringBuffer2.append("\n"); + } + } + if (this.attributes_count > 0) { + stringBuffer.append("\nAttribute(s) = \n"); + int value3 = 0; + for (int value4 = value3; value4 < this.attributes_count; value4 = value3) { + StringBuffer stringBuffer3 = stringBuffer.append(this.attributes[value3].toString()); + value3++; + stringBuffer3.append("\n"); + } + } + return stringBuffer.toString(); + } + + public final int getMax_locals() { + return this.max_locals; + } + + public final void setExceptionTable(CodeException[] codeExceptions) { + this.exception_table = codeExceptions; + this.exception_table_length = codeExceptions == null ? 0 : codeExceptions.length; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/CodeException.java b/src/main/java/com/allatori/lib/bcel/classfile/CodeException.java new file mode 100644 index 0000000..f5a3a7d --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/CodeException.java @@ -0,0 +1,117 @@ +package com.allatori.lib.bcel.classfile; + +import com.allatori.lib.bcel.Constants; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.Serializable; + +public final class CodeException implements Cloneable, Constants, Node, Serializable { + + public int handler_pc; + + public int end_pc; + + public int start_pc; + + public int catch_type; + + public CodeException(int start_pc, int end_pc, int handler_pc, int catch_type) { + super(); + this.start_pc = start_pc; + this.end_pc = end_pc; + this.handler_pc = handler_pc; + this.catch_type = catch_type; + } + + public final int getStart_pc() { + return this.start_pc; + } + + public CodeException(CodeException codeException) { + this( + codeException.getStart_pc(), + codeException.getEnd_pc(), + codeException.getHandler_pc(), + codeException.getCatch_type()); + } + + public CodeException copy() { + try { + return (CodeException) this.clone(); + } catch (CloneNotSupportedException cloneNotSupportedException) { + return null; + } + } + + public final int getEnd_pc() { + return this.end_pc; + } + + public final int getCatch_type() { + return this.catch_type; + } + + @Override + public void accept(Visitor visitor) { + visitor.visitCodeException(this); + } + + public final int getHandler_pc() { + return this.handler_pc; + } + + public final void setEnd_pc(int end_pc) { + this.end_pc = end_pc; + } + + public final void dump(DataOutputStream dataOutputStream) throws IOException { + dataOutputStream.writeShort(this.start_pc); + dataOutputStream.writeShort(this.end_pc); + dataOutputStream.writeShort(this.handler_pc); + dataOutputStream.writeShort(this.catch_type); + } + + public final void setStart_pc(int start_pc) { + this.start_pc = start_pc; + } + + public final String toString(ConstantPool constantPool, boolean matches) { + String text; + if (this.catch_type == 0) { + text = "(0)"; + } else { + text = + "" + + Utility.getText(constantPool.createText(this.catch_type, (byte) 7), false) + + (matches + ? new StringBuilder() + .insert(0, "(") + .append(this.catch_type) + .append(")") + .toString() + : ""); + } + return this.start_pc + "\t" + this.end_pc + "\t" + this.handler_pc + "\t" + text; + } + + public final void setHandler_pc(int handler_pc) { + this.handler_pc = handler_pc; + } + + public final String toString(ConstantPool constantPool) { + return this.toString(constantPool, true); + } + + public final void setCatch_type(int catch_type) { + this.catch_type = catch_type; + } + + public CodeException(DataInputStream dataInputStream) throws IOException { + this( + dataInputStream.readUnsignedShort(), + dataInputStream.readUnsignedShort(), + dataInputStream.readUnsignedShort(), + dataInputStream.readUnsignedShort()); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/Constant.java b/src/main/java/com/allatori/lib/bcel/classfile/Constant.java new file mode 100644 index 0000000..d639ba4 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/Constant.java @@ -0,0 +1,101 @@ +package com.allatori.lib.bcel.classfile; + +import com.allatori.lib.bcel.util.BCELComparator; +import com.allatori.lib.bcel.util.comparator.ConstantComparator; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.Serializable; + +public abstract class Constant implements Cloneable, Node, Serializable { + + public byte tag; + + public static BCELComparator _cmp = new ConstantComparator(); + + @Override + public int hashCode() { + return _cmp.hashCode(this); + } + + public Constant copy() { + try { + return (Constant) super.clone(); + } catch (CloneNotSupportedException cloneNotSupportedException) { + return null; + } + } + + public static final Constant readConstant(DataInputStream dataInputStream) + throws IOException, ClassFormatException { + byte value; + switch (value = dataInputStream.readByte()) { + case 1: + return new ConstantUtf8(dataInputStream); + case 2: + case 13: + case 14: + case 17: + default: + throw new ClassFormatException(("Invalid byte tag in constant pool: " + value)); + case 3: + return new ConstantInteger(dataInputStream); + case 4: + return new ConstantFloat(dataInputStream); + case 5: + return new ConstantLong(dataInputStream); + case 6: + return new ConstantDouble(dataInputStream); + case 7: + return new ConstantClass(dataInputStream); + case 8: + return new ConstantString(dataInputStream); + case 9: + return new ConstantFieldref(dataInputStream); + case 10: + return new ConstantMethodref(dataInputStream); + case 11: + return new ConstantInterfaceMethodref(dataInputStream); + case 12: + return new ConstantNameAndType(dataInputStream); + case 15: + return new ConstantMethodHandle(dataInputStream); + case 16: + return new ConstantMethodType(dataInputStream); + case 18: + return new ConstantInvokeDynamic(dataInputStream); + } + } + + public abstract void dump(DataOutputStream dataOutputStream) throws IOException; + + public static BCELComparator getComparator() { + return _cmp; + } + + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } + + public static void setComparator(BCELComparator bCELComparator) { + _cmp = bCELComparator; + } + + public Constant(byte tag) { + super(); + this.tag = tag; + } + + @Override + public boolean equals(Object result) { + return _cmp.equals(this, result); + } + + public final byte getTag() { + return this.tag; + } + + @Override + public abstract void accept(Visitor visitor); +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/ConstantCP.java b/src/main/java/com/allatori/lib/bcel/classfile/ConstantCP.java new file mode 100644 index 0000000..9a9470d --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/ConstantCP.java @@ -0,0 +1,53 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public abstract class ConstantCP extends Constant { + + public int class_index; + + public int name_and_type_index; + + public String getClass(ConstantPool constantPool) { + return constantPool.getText(this.class_index, (byte) 7); + } + + public final void setClass_index(int class_index) { + this.class_index = class_index; + } + + public ConstantCP(byte value, int class_index, int name_and_type_index) { + super(value); + this.class_index = class_index; + this.name_and_type_index = name_and_type_index; + } + + public final int getName_and_type_index() { + return this.name_and_type_index; + } + + public ConstantCP(byte value, DataInputStream dataInputStream) throws IOException { + this(value, dataInputStream.readUnsignedShort(), dataInputStream.readUnsignedShort()); + } + + public ConstantCP(ConstantCP constantCP) { + this(constantCP.getTag(), constantCP.getClass_index(), constantCP.getName_and_type_index()); + } + + public final int getClass_index() { + return this.class_index; + } + + @Override + public final void dump(DataOutputStream dataOutputStream) throws IOException { + dataOutputStream.writeByte(this.tag); + dataOutputStream.writeShort(this.class_index); + dataOutputStream.writeShort(this.name_and_type_index); + } + + public final void setName_and_type_index(int name_and_type_index) { + this.name_and_type_index = name_and_type_index; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/ConstantClass.java b/src/main/java/com/allatori/lib/bcel/classfile/ConstantClass.java new file mode 100644 index 0000000..bf4bd9f --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/ConstantClass.java @@ -0,0 +1,51 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public final class ConstantClass extends Constant implements ConstantObject { + + public int name_index; + + public ConstantClass(DataInputStream dataInputStream) throws IOException { + this(dataInputStream.readUnsignedShort()); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitConstantClass(this); + } + + public final void setNameIndex(int name_index) { + this.name_index = name_index; + } + + public ConstantClass(int name_index) { + super((byte) 7); + this.name_index = name_index; + } + + public final int getNameIndex() { + return this.name_index; + } + + public ConstantClass(ConstantClass constantClass) { + this(constantClass.getNameIndex()); + } + + @Override + public Object getConstantValue(ConstantPool constantPool) { + return ((ConstantUtf8) constantPool.getConstant(this.name_index, (byte) 1)).getBytes(); + } + + public String getBytes(ConstantPool constantPool) { + return (String) this.getConstantValue(constantPool); + } + + @Override + public final void dump(DataOutputStream dataOutputStream) throws IOException { + dataOutputStream.writeByte(this.tag); + dataOutputStream.writeShort(this.name_index); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/ConstantDouble.java b/src/main/java/com/allatori/lib/bcel/classfile/ConstantDouble.java new file mode 100644 index 0000000..7ebafdc --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/ConstantDouble.java @@ -0,0 +1,47 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public final class ConstantDouble extends Constant implements ConstantObject { + + public double bytes; + + @Override + public void accept(Visitor visitor) { + visitor.visitConstantDouble(this); + } + + public ConstantDouble(double bytes) { + super((byte) 6); + this.bytes = bytes; + } + + public ConstantDouble(DataInputStream dataInputStream) throws IOException { + this(dataInputStream.readDouble()); + } + + @Override + public final void dump(DataOutputStream dataOutputStream) throws IOException { + dataOutputStream.writeByte(this.tag); + dataOutputStream.writeDouble(this.bytes); + } + + public final double getBytes() { + return this.bytes; + } + + public ConstantDouble(ConstantDouble constantDouble) { + this(constantDouble.getBytes()); + } + + @Override + public Object getConstantValue(ConstantPool constantPool) { + return new Double(this.bytes); + } + + public final void setBytes(double bytes) { + this.bytes = bytes; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/ConstantFieldref.java b/src/main/java/com/allatori/lib/bcel/classfile/ConstantFieldref.java new file mode 100644 index 0000000..0960212 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/ConstantFieldref.java @@ -0,0 +1,24 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInputStream; +import java.io.IOException; + +public final class ConstantFieldref extends ConstantCP { + + public ConstantFieldref(int value, int value2) { + super((byte) 9, value, value2); + } + + public ConstantFieldref(ConstantFieldref constantFieldref) { + super((byte) 9, constantFieldref.getClass_index(), constantFieldref.getName_and_type_index()); + } + + public ConstantFieldref(DataInputStream dataInputStream) throws IOException { + super((byte) 9, dataInputStream); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitConstantFieldref(this); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/ConstantFloat.java b/src/main/java/com/allatori/lib/bcel/classfile/ConstantFloat.java new file mode 100644 index 0000000..81d2d2f --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/ConstantFloat.java @@ -0,0 +1,47 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public final class ConstantFloat extends Constant implements ConstantObject { + + public float bytes; + + @Override + public final void dump(DataOutputStream dataOutputStream) throws IOException { + dataOutputStream.writeByte(this.tag); + dataOutputStream.writeFloat(this.bytes); + } + + public ConstantFloat(float bytes) { + super((byte) 4); + this.bytes = bytes; + } + + @Override + public Object getConstantValue(ConstantPool constantPool) { + return new Float(this.bytes); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitConstantFloat(this); + } + + public ConstantFloat(ConstantFloat constantFloat) { + this(constantFloat.getBytes()); + } + + public final void setBytes(float bytes) { + this.bytes = bytes; + } + + public final float getBytes() { + return this.bytes; + } + + public ConstantFloat(DataInputStream dataInputStream) throws IOException { + this(dataInputStream.readFloat()); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/ConstantInteger.java b/src/main/java/com/allatori/lib/bcel/classfile/ConstantInteger.java new file mode 100644 index 0000000..da9685b --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/ConstantInteger.java @@ -0,0 +1,47 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public final class ConstantInteger extends Constant implements ConstantObject { + + public int bytes; + + public ConstantInteger(DataInputStream dataInputStream) throws IOException { + this(dataInputStream.readInt()); + } + + @Override + public final void dump(DataOutputStream dataOutputStream) throws IOException { + dataOutputStream.writeByte(this.tag); + dataOutputStream.writeInt(this.bytes); + } + + public final int getBytes() { + return this.bytes; + } + + @Override + public Object getConstantValue(ConstantPool constantPool) { + return new Integer(this.bytes); + } + + public final void setBytes(int bytes) { + this.bytes = bytes; + } + + public ConstantInteger(int bytes) { + super((byte) 3); + this.bytes = bytes; + } + + public ConstantInteger(ConstantInteger constantInteger) { + this(constantInteger.getBytes()); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitConstantInteger(this); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/ConstantInterfaceMethodref.java b/src/main/java/com/allatori/lib/bcel/classfile/ConstantInterfaceMethodref.java new file mode 100644 index 0000000..9303c8b --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/ConstantInterfaceMethodref.java @@ -0,0 +1,27 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInputStream; +import java.io.IOException; + +public final class ConstantInterfaceMethodref extends ConstantCP { + + public ConstantInterfaceMethodref(DataInputStream dataInputStream) throws IOException { + super((byte) 11, dataInputStream); + } + + public ConstantInterfaceMethodref(ConstantInterfaceMethodref constantInterfaceMethodref) { + super( + (byte) 11, + constantInterfaceMethodref.getClass_index(), + constantInterfaceMethodref.getName_and_type_index()); + } + + public ConstantInterfaceMethodref(int value, int value2) { + super((byte) 11, value, value2); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitConstantInterfaceMethodref(this); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/ConstantInvokeDynamic.java b/src/main/java/com/allatori/lib/bcel/classfile/ConstantInvokeDynamic.java new file mode 100644 index 0000000..3511053 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/ConstantInvokeDynamic.java @@ -0,0 +1,54 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInput; +import java.io.DataOutputStream; +import java.io.IOException; + +public final class ConstantInvokeDynamic extends Constant { + + public int count; + + public int count2; + + public ConstantInvokeDynamic(int count, int count2) { + super((byte) 18); + this.count = count; + this.count2 = count2; + } + + public int getBootstrapMethodAttrIndex() { + return this.count; + } + + @Override + public final void dump(DataOutputStream dataOutputStream) throws IOException { + dataOutputStream.writeByte(this.tag); + dataOutputStream.writeShort(this.count); + dataOutputStream.writeShort(this.count2); + } + + public void setCount(int count) { + this.count = count; + } + + public void setCount2(int count2) { + this.count2 = count2; + } + + public ConstantInvokeDynamic(ConstantInvokeDynamic constantInvokeDynamic) { + this( + constantInvokeDynamic.getBootstrapMethodAttrIndex(), + constantInvokeDynamic.getBootstrapMethodAttrIndex2()); + } + + public ConstantInvokeDynamic(DataInput dataInput) throws IOException { + this(dataInput.readUnsignedShort(), dataInput.readUnsignedShort()); + } + + public int getBootstrapMethodAttrIndex2() { + return this.count2; + } + + @Override + public void accept(Visitor visitor) {} +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/ConstantLong.java b/src/main/java/com/allatori/lib/bcel/classfile/ConstantLong.java new file mode 100644 index 0000000..27747cf --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/ConstantLong.java @@ -0,0 +1,47 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public final class ConstantLong extends Constant implements ConstantObject { + + public long bytes; + + @Override + public void accept(Visitor visitor) { + visitor.visitConstantLong(this); + } + + public final long getBytes() { + return this.bytes; + } + + public final void setBytes(long bytes) { + this.bytes = bytes; + } + + public ConstantLong(long bytes) { + super((byte) 5); + this.bytes = bytes; + } + + public ConstantLong(DataInputStream dataInputStream) throws IOException { + this(dataInputStream.readLong()); + } + + @Override + public Object getConstantValue(ConstantPool constantPool) { + return new Long(this.bytes); + } + + public ConstantLong(ConstantLong constantLong) { + this(constantLong.getBytes()); + } + + @Override + public final void dump(DataOutputStream dataOutputStream) throws IOException { + dataOutputStream.writeByte(this.tag); + dataOutputStream.writeLong(this.bytes); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/ConstantMethodHandle.java b/src/main/java/com/allatori/lib/bcel/classfile/ConstantMethodHandle.java new file mode 100644 index 0000000..4a60ac4 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/ConstantMethodHandle.java @@ -0,0 +1,52 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInput; +import java.io.DataOutputStream; +import java.io.IOException; + +public final class ConstantMethodHandle extends Constant { + + public int reference_kind; + + public int reference_index; + + @Override + public final void dump(DataOutputStream dataOutputStream) throws IOException { + dataOutputStream.writeByte(this.tag); + dataOutputStream.writeByte(this.reference_kind); + dataOutputStream.writeShort(this.reference_index); + } + + public ConstantMethodHandle(int reference_kind, int reference_index) { + super((byte) 15); + this.reference_kind = reference_kind; + this.reference_index = reference_index; + } + + public ConstantMethodHandle(ConstantMethodHandle constantMethodHandle) { + this(constantMethodHandle.getReference_kind(), constantMethodHandle.getReference_index()); + } + + @Override + public void accept(Visitor visitor) {} + + public void setReference_kind(int reference_kind) { + this.reference_kind = reference_kind; + } + + public int getReference_kind() { + return this.reference_kind; + } + + public void setReference_index(int reference_index) { + this.reference_index = reference_index; + } + + public int getReference_index() { + return this.reference_index; + } + + public ConstantMethodHandle(DataInput dataInput) throws IOException { + this(dataInput.readUnsignedByte(), dataInput.readUnsignedShort()); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/ConstantMethodType.java b/src/main/java/com/allatori/lib/bcel/classfile/ConstantMethodType.java new file mode 100644 index 0000000..1255eda --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/ConstantMethodType.java @@ -0,0 +1,40 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInput; +import java.io.DataOutputStream; +import java.io.IOException; + +public final class ConstantMethodType extends Constant { + + public int descriptor_index; + + public ConstantMethodType(int descriptor_index) { + super((byte) 16); + this.descriptor_index = descriptor_index; + } + + public ConstantMethodType(DataInput dataInput) throws IOException { + this(dataInput.readUnsignedShort()); + } + + @Override + public void accept(Visitor visitor) {} + + public ConstantMethodType(ConstantMethodType constantMethodType) { + this(constantMethodType.getDescriptorIndex()); + } + + @Override + public final void dump(DataOutputStream dataOutputStream) throws IOException { + dataOutputStream.writeByte(this.tag); + dataOutputStream.writeShort(this.descriptor_index); + } + + public void setDescriptorIndex(int descriptor_index) { + this.descriptor_index = descriptor_index; + } + + public int getDescriptorIndex() { + return this.descriptor_index; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/ConstantMethodref.java b/src/main/java/com/allatori/lib/bcel/classfile/ConstantMethodref.java new file mode 100644 index 0000000..b6dc097 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/ConstantMethodref.java @@ -0,0 +1,25 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInputStream; +import java.io.IOException; + +public final class ConstantMethodref extends ConstantCP { + + public ConstantMethodref(ConstantMethodref constantMethodref) { + super( + (byte) 10, constantMethodref.getClass_index(), constantMethodref.getName_and_type_index()); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitConstantMethodref(this); + } + + public ConstantMethodref(DataInputStream dataInputStream) throws IOException { + super((byte) 10, dataInputStream); + } + + public ConstantMethodref(int value, int value2) { + super((byte) 10, value, value2); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/ConstantNameAndType.java b/src/main/java/com/allatori/lib/bcel/classfile/ConstantNameAndType.java new file mode 100644 index 0000000..734f89f --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/ConstantNameAndType.java @@ -0,0 +1,62 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public final class ConstantNameAndType extends Constant { + + public int signature_index; + + public int name_index; + + public final void setName_index(int name_index) { + this.name_index = name_index; + } + + public final int getName_index() { + return this.name_index; + } + + public ConstantNameAndType(DataInputStream dataInputStream) throws IOException { + this(dataInputStream.readUnsignedShort(), dataInputStream.readUnsignedShort()); + } + + @Override + public final void dump(DataOutputStream dataOutputStream) throws IOException { + dataOutputStream.writeByte(this.tag); + dataOutputStream.writeShort(this.name_index); + dataOutputStream.writeShort(this.signature_index); + } + + public final int getSignature_index() { + return this.signature_index; + } + + public ConstantNameAndType(ConstantNameAndType constantNameAndType) { + this(constantNameAndType.getName_index(), constantNameAndType.getSignature_index()); + } + + public final String getText(ConstantPool constantPool) { + return constantPool.getText(this.getName_index(), (byte) 1); + } + + public ConstantNameAndType(int name_index, int signature_index) { + super((byte) 12); + this.name_index = name_index; + this.signature_index = signature_index; + } + + public final String getText2(ConstantPool constantPool) { + return constantPool.getText(this.getSignature_index(), (byte) 1); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitConstantNameAndType(this); + } + + public final void setSignature_index(int signature_index) { + this.signature_index = signature_index; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/ConstantObject.java b/src/main/java/com/allatori/lib/bcel/classfile/ConstantObject.java new file mode 100644 index 0000000..47fb7e2 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/ConstantObject.java @@ -0,0 +1,6 @@ +package com.allatori.lib.bcel.classfile; + +public interface ConstantObject { + + Object getConstantValue(ConstantPool constantPool); +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/ConstantPool.java b/src/main/java/com/allatori/lib/bcel/classfile/ConstantPool.java new file mode 100644 index 0000000..61e59d4 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/ConstantPool.java @@ -0,0 +1,197 @@ +package com.allatori.lib.bcel.classfile; + +import com.allatori.lib.bcel.Constants; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.Serializable; + +public class ConstantPool implements Cloneable, Node, Serializable { + + public Constant[] constant_pool; + + public int constant_pool_count; + + public String getText(int value, byte value2) { + return this.constantToString(this.getConstant(value, value2)); + } + + public static final String escape(String text) { + int size = text.length(); + StringBuffer stringBuffer = new StringBuffer(size + 5); + char[] values = text.toCharArray(); + int value; + for (int value2 = value = 0; value2 < size; value2 = ++value) { + switch (values[value]) { + case '\b': + stringBuffer.append("\\b"); + break; + case '\t': + stringBuffer.append("\\t"); + break; + case '\n': + stringBuffer.append("\\n"); + break; + case '\r': + stringBuffer.append("\\r"); + break; + case '"': + stringBuffer.append("\\\""); + break; + default: + stringBuffer.append(values[value]); + } + } + return stringBuffer.toString(); + } + + public String createText(int value, byte value2) { + Constant constant = this.getConstant(value, value2); + int value3; + ConstantPool constantPool; + switch (value2) { + case 7: + value3 = ((ConstantClass) constant).getNameIndex(); + constantPool = this; + break; + case 8: + value3 = ((ConstantString) constant).getStringIndex(); + constantPool = this; + break; + default: + throw new RuntimeException(("getConstantString called with illegal tag " + value2)); + } + return ((ConstantUtf8) constantPool.getConstant(value3, (byte) 1)).getBytes(); + } + + public ConstantPool(DataInputStream dataInputStream) throws IOException, ClassFormatException { + this.constant_pool_count = dataInputStream.readUnsignedShort(); + this.constant_pool = new Constant[this.constant_pool_count]; + int value; + for (int value2 = value = 1; value2 < this.constant_pool_count; value2 = ++value) { + this.constant_pool[value] = Constant.readConstant(dataInputStream); + byte value3; + if ((value3 = this.constant_pool[value].getTag()) == 6 || value3 == 5) { + value++; + } + } + } + + public Constant getConstant(int value, byte value2) throws ClassFormatException { + Constant constant; + if ((constant = this.getConstant(value)) == null) { + throw new ClassFormatException(("Constant pool at index " + value + " is null.")); + } else if (constant.getTag() != value2) { + throw new ClassFormatException( + ("Expected class `" + + Constants.TEXTS7[value2] + + "' at index " + + value + + " and got " + + constant)); + } else { + return constant; + } + } + + @Override + public void accept(Visitor visitor) { + visitor.visitConstantPool(this); + } + + public void setConstant(int value, Constant constant) { + this.constant_pool[value] = constant; + } + + public Constant getConstant(int value) throws ClassFormatException { + if (value < this.constant_pool.length && value >= 0) { + return this.constant_pool[value]; + } else { + throw new ClassFormatException( + ("Invalid constant pool reference: " + + value + + ". Constant pool size is: " + + this.constant_pool.length)); + } + } + + public int getLength() { + return this.constant_pool_count; + } + + public String constantToString(Constant constant) throws IllegalArgumentException { + byte value; + switch (value = constant.getTag()) { + case 1: + return ((ConstantUtf8) constant).getBytes(); + case 2: + default: + throw new RuntimeException(("Unknown constant type " + value)); + case 3: + return "" + ((ConstantInteger) constant).getBytes(); + case 4: + return "" + ((ConstantFloat) constant).getBytes(); + case 5: + return "" + ((ConstantLong) constant).getBytes(); + case 6: + return "" + ((ConstantDouble) constant).getBytes(); + case 7: + int nameIndex = ((ConstantClass) constant).getNameIndex(); + return Utility.getText( + ((ConstantUtf8) this.getConstant(nameIndex, (byte) 1)).getBytes(), false); + case 8: + int stringIndex = ((ConstantString) constant).getStringIndex(); + Constant constant2 = this.getConstant(stringIndex, (byte) 1); + return "\"" + escape(((ConstantUtf8) constant2).getBytes()) + "\""; + case 9: + case 10: + case 11: + return this.getText(((ConstantCP) constant).getClass_index(), (byte) 7) + + "." + + this.getText(((ConstantCP) constant).getName_and_type_index(), (byte) 12); + case 12: + return this.getText(((ConstantNameAndType) constant).getName_index(), (byte) 1) + + " " + + this.getText(((ConstantNameAndType) constant).getSignature_index(), (byte) 1); + } + } + + public Constant[] getConstantPool() { + return this.constant_pool; + } + + public void setConstantPool(Constant[] constants) { + this.constant_pool = constants; + this.constant_pool_count = constants == null ? 0 : constants.length; + } + + public ConstantPool copy() { + ConstantPool constantPool = null; + try { + (constantPool = (ConstantPool) this.clone()).constant_pool = + new Constant[this.constant_pool_count]; + for (int index = 1; index < this.constant_pool_count; index++) { + if (this.constant_pool[index] != null) { + constantPool.constant_pool[index] = this.constant_pool[index].copy(); + } + } + } catch (CloneNotSupportedException cloneNotSupportedException) { + } + return constantPool; + } + + public void dump(DataOutputStream dataOutputStream) throws IOException { + int value = 1; + dataOutputStream.writeShort(this.constant_pool_count); + for (int index = 1; value < this.constant_pool_count; value = ++index) { + if (this.constant_pool[index] != null) { + this.constant_pool[index].dump(dataOutputStream); + } + } + } + + public ConstantPool(Constant[] constants) { + super(); + this.setConstantPool(constants); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/ConstantString.java b/src/main/java/com/allatori/lib/bcel/classfile/ConstantString.java new file mode 100644 index 0000000..2ebc8fe --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/ConstantString.java @@ -0,0 +1,51 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public final class ConstantString extends Constant implements ConstantObject { + + public int string_index; + + public String getBytes(ConstantPool constantPool) { + return (String) this.getConstantValue(constantPool); + } + + public ConstantString(DataInputStream dataInputStream) throws IOException { + this(dataInputStream.readUnsignedShort()); + } + + public ConstantString(int string_index) { + super((byte) 8); + this.string_index = string_index; + } + + public ConstantString(ConstantString constantString) { + this(constantString.getStringIndex()); + } + + @Override + public final void dump(DataOutputStream dataOutputStream) throws IOException { + dataOutputStream.writeByte(this.tag); + dataOutputStream.writeShort(this.string_index); + } + + public final int getStringIndex() { + return this.string_index; + } + + @Override + public void accept(Visitor visitor) { + visitor.visitConstantString(this); + } + + public final void setStringIndex(int string_index) { + this.string_index = string_index; + } + + @Override + public Object getConstantValue(ConstantPool constantPool) { + return ((ConstantUtf8) constantPool.getConstant(this.string_index, (byte) 1)).getBytes(); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/ConstantUtf8.java b/src/main/java/com/allatori/lib/bcel/classfile/ConstantUtf8.java new file mode 100644 index 0000000..2e0fe93 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/ConstantUtf8.java @@ -0,0 +1,46 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public final class ConstantUtf8 extends Constant { + + public String bytes; + + @Override + public void accept(Visitor visitor) { + visitor.visitConstantUtf8(this); + } + + public ConstantUtf8(ConstantUtf8 constantUtf8) { + this(constantUtf8.getBytes()); + } + + public final void setBytes(String bytes) { + this.bytes = bytes; + } + + public ConstantUtf8(DataInputStream dataInputStream) throws IOException { + super((byte) 1); + this.bytes = dataInputStream.readUTF(); + } + + public final String getBytes() { + return this.bytes; + } + + @Override + public final void dump(DataOutputStream dataOutputStream) throws IOException { + dataOutputStream.writeByte(this.tag); + dataOutputStream.writeUTF(this.bytes); + } + + public ConstantUtf8(String bytes) { + super((byte) 1); + if (bytes == null) { + throw new IllegalArgumentException("bytes must not be null!"); + } + this.bytes = bytes; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/ConstantValue.java b/src/main/java/com/allatori/lib/bcel/classfile/ConstantValue.java new file mode 100644 index 0000000..12b0be4 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/ConstantValue.java @@ -0,0 +1,55 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public final class ConstantValue extends Attribute { + + public int constantvalue_index; + + @Override + public void accept(Visitor visitor) { + visitor.visitConstantValue(this); + } + + public ConstantValue(int value, int value2, int constantvalue_index, ConstantPool constantPool) { + super((byte) 1, value, value2, constantPool); + this.constantvalue_index = constantvalue_index; + } + + @Override + public Attribute copy(ConstantPool constantPool) { + ConstantValue constantValue = (ConstantValue) this.clone(); + constantValue.constant_pool = constantPool; + return constantValue; + } + + @Override + public final void dump(DataOutputStream dataOutputStream) throws IOException { + super.dump(dataOutputStream); + dataOutputStream.writeShort(this.constantvalue_index); + } + + public final void setConstantValueIndex(int constantvalue_index) { + this.constantvalue_index = constantvalue_index; + } + + public ConstantValue( + int value, int value2, DataInputStream dataInputStream, ConstantPool constantPool) + throws IOException { + this(value, value2, dataInputStream.readUnsignedShort(), constantPool); + } + + public final int getConstantValueIndex() { + return this.constantvalue_index; + } + + public ConstantValue(ConstantValue constantValue) { + this( + constantValue.getName_index(), + constantValue.getLength(), + constantValue.getConstantValueIndex(), + constantValue.getConstantPool()); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/Deprecated.java b/src/main/java/com/allatori/lib/bcel/classfile/Deprecated.java new file mode 100644 index 0000000..33c759c --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/Deprecated.java @@ -0,0 +1,66 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public final class Deprecated extends Attribute { + + public byte[] bytes; + + @Override + public final void dump(DataOutputStream dataOutputStream) throws IOException { + super.dump(dataOutputStream); + if (this.length > 0) { + dataOutputStream.write(this.bytes, 0, this.length); + } + } + + public Deprecated(Deprecated deprecated) { + this( + deprecated.getName_index(), + deprecated.getLength(), + deprecated.getBytes(), + deprecated.getConstantPool()); + } + + public Deprecated( + int value, int value2, DataInputStream dataInputStream, ConstantPool constantPool) + throws IOException { + this(value, value2, (byte[]) null, constantPool); + if (value2 > 0) { + this.bytes = new byte[value2]; + dataInputStream.readFully(this.bytes); + System.err.println("Deprecated attribute with length > 0"); + } + } + + public final void setBytes(byte[] bytes) { + this.bytes = bytes; + } + + public Deprecated(int value, int value2, byte[] bytes, ConstantPool constantPool) { + super((byte) 8, value, value2, constantPool); + this.bytes = bytes; + } + + @Override + public void accept(Visitor visitor) { + visitor.visitDeprecated(this); + } + + @Override + public Attribute copy(ConstantPool constantPool) { + Deprecated deprecated = (Deprecated) this.clone(); + if (this.bytes != null) { + deprecated.bytes = new byte[this.bytes.length]; + System.arraycopy(this.bytes, 0, deprecated.bytes, 0, this.bytes.length); + } + deprecated.constant_pool = constantPool; + return deprecated; + } + + public final byte[] getBytes() { + return this.bytes; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/DescendingVisitor.java b/src/main/java/com/allatori/lib/bcel/classfile/DescendingVisitor.java new file mode 100644 index 0000000..6b4fb5f --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/DescendingVisitor.java @@ -0,0 +1,397 @@ +package com.allatori.lib.bcel.classfile; + +import java.util.Stack; + +public class DescendingVisitor implements Visitor { + + public Stack stack; + + public Visitor visitor; + + public JavaClass clazz; + + public void visit() { + this.clazz.accept(this); + } + + @Override + public void visitLocalVariableTypeTable(LocalVariableTypeTable localVariableTypeTable) { + this.stack.push(localVariableTypeTable); + localVariableTypeTable.accept(this.visitor); + this.stack.pop(); + } + + @Override + public void visitUnknown(Unknown unknown) { + this.stack.push(unknown); + unknown.accept(this.visitor); + this.stack.pop(); + } + + @Override + public void visitSignature(Signature signature) { + this.stack.push(signature); + signature.accept(this.visitor); + this.stack.pop(); + } + + @Override + public void visitConstantInterfaceMethodref( + ConstantInterfaceMethodref constantInterfaceMethodref) { + this.stack.push(constantInterfaceMethodref); + constantInterfaceMethodref.accept(this.visitor); + this.stack.pop(); + } + + public Object predecessor() { + return this.predecessor(0); + } + + public DescendingVisitor(JavaClass javaClass, Visitor visitor2) { + super(); + this.stack = new Stack(); + this.clazz = javaClass; + this.visitor = visitor2; + } + + @Override + public void visitConstantString(ConstantString constantString) { + this.stack.push(constantString); + constantString.accept(this.visitor); + this.stack.pop(); + } + + public Object current() { + return this.stack.peek(); + } + + @Override + public void visitLineNumberTable(LineNumberTable lineNumberTable) { + this.stack.push(lineNumberTable); + lineNumberTable.accept(this.visitor); + LineNumber[] lineNumberTable2 = lineNumberTable.getLineNumberTable(); + int value = 0; + for (int value2 = value; value2 < lineNumberTable2.length; value2 = value) { + int value3 = value; + value++; + lineNumberTable2[value3].accept(this); + } + this.stack.pop(); + } + + @Override + public void visitSynthetic(Synthetic synthetic) { + this.stack.push(synthetic); + synthetic.accept(this.visitor); + this.stack.pop(); + } + + @Override + public void visitConstantFieldref(ConstantFieldref constantFieldref) { + this.stack.push(constantFieldref); + constantFieldref.accept(this.visitor); + this.stack.pop(); + } + + @Override + public void visitConstantPool(ConstantPool constantPool) { + this.stack.push(constantPool); + constantPool.accept(this.visitor); + Constant[] constantPool2 = constantPool.getConstantPool(); + int value = 1; + for (int value2 = value; value2 < constantPool2.length; value2 = ++value) { + if (constantPool2[value] != null) { + constantPool2[value].accept(this); + } + } + this.stack.pop(); + } + + @Override + public void visitConstantClass(ConstantClass constantClass) { + this.stack.push(constantClass); + constantClass.accept(this.visitor); + this.stack.pop(); + } + + @Override + public void visitLineNumber(LineNumber lineNumber) { + this.stack.push(lineNumber); + lineNumber.accept(this.visitor); + this.stack.pop(); + } + + @Override + public void visitParameterAnnotation(ParameterAnnotations parameterAnnotations) { + this.stack.push(parameterAnnotations); + parameterAnnotations.accept(this.visitor); + this.stack.pop(); + } + + @Override + public void visitStackMap(StackMap stackMap) { + this.stack.push(stackMap); + stackMap.accept(this.visitor); + StackMapEntry[] stackMap2 = stackMap.getStackMap(); + int value = 0; + for (int value2 = value; value2 < stackMap2.length; value2 = value) { + int value3 = value; + value++; + stackMap2[value3].accept(this); + } + this.stack.pop(); + } + + @Override + public void visitCodeException(CodeException codeException) { + this.stack.push(codeException); + codeException.accept(this.visitor); + this.stack.pop(); + } + + @Override + public void visitAnnotation(Annotations annotations) { + this.stack.push(annotations); + annotations.accept(this.visitor); + AnnotationEntry[] annotationEntries = annotations.getAnnotationEntries(); + int value = 0; + for (int value2 = value; value2 < annotationEntries.length; value2 = value) { + int value3 = value; + value++; + annotationEntries[value3].accept(this); + } + this.stack.pop(); + } + + @Override + public void visitStackMapEntry(StackMapEntry stackMapEntry) { + this.stack.push(stackMapEntry); + stackMapEntry.accept(this.visitor); + this.stack.pop(); + } + + @Override + public void visitConstantMethodref(ConstantMethodref constantMethodref) { + this.stack.push(constantMethodref); + constantMethodref.accept(this.visitor); + this.stack.pop(); + } + + @Override + public void visitConstantFloat(ConstantFloat constantFloat) { + this.stack.push(constantFloat); + constantFloat.accept(this.visitor); + this.stack.pop(); + } + + @Override + public void visitDeprecated(Deprecated deprecated) { + this.stack.push(deprecated); + deprecated.accept(this.visitor); + this.stack.pop(); + } + + @Override + public void visitLocalVariableTable(LocalVariableTable localVariableTable) { + this.stack.push(localVariableTable); + localVariableTable.accept(this.visitor); + LocalVariable[] localVariableTable2 = localVariableTable.getLocalVariableTable(); + int value = 0; + for (int value2 = value; value2 < localVariableTable2.length; value2 = value) { + int value3 = value; + value++; + localVariableTable2[value3].accept(this); + } + this.stack.pop(); + } + + @Override + public void visitConstantNameAndType(ConstantNameAndType constantNameAndType) { + this.stack.push(constantNameAndType); + constantNameAndType.accept(this.visitor); + this.stack.pop(); + } + + @Override + public void visitConstantDouble(ConstantDouble constantDouble) { + this.stack.push(constantDouble); + constantDouble.accept(this.visitor); + this.stack.pop(); + } + + public Object predecessor(int value) { + int value2; + return (value2 = this.stack.size()) >= 2 && value >= 0 + ? this.stack.elementAt(value2 - (value + 2)) + : null; + } + + @Override + public void visitLocalVariable(LocalVariable localVariable) { + this.stack.push(localVariable); + localVariable.accept(this.visitor); + this.stack.pop(); + } + + @Override + public void visitInnerClass(InnerClass innerClass) { + this.stack.push(innerClass); + innerClass.accept(this.visitor); + this.stack.pop(); + } + + @Override + public void visitSourceFile(SourceFile sourceFile) { + this.stack.push(sourceFile); + sourceFile.accept(this.visitor); + this.stack.pop(); + } + + @Override + public void visitCode(Code code) { + this.stack.push(code); + code.accept(this.visitor); + CodeException[] exceptionTable = code.getExceptionTable(); + int value = 0; + for (int value2 = value; value2 < exceptionTable.length; value2 = value) { + int value3 = value; + value++; + exceptionTable[value3].accept(this); + } + Attribute[] attributes = code.getAttributes(); + int value4; + for (int value5 = value4 = 0; value5 < attributes.length; value5 = value4) { + int value6 = value4; + value4++; + attributes[value6].accept(this); + } + this.stack.pop(); + } + + @Override + public void visitJavaClass(JavaClass javaClass) { + this.stack.push(javaClass); + javaClass.accept(this.visitor); + Field[] fields = javaClass.getFields(); + int value = 0; + for (int value2 = value; value2 < fields.length; value2 = value) { + int value3 = value; + value++; + fields[value3].accept(this); + } + Method[] methods = javaClass.getMethods(); + int value4; + for (int value5 = value4 = 0; value5 < methods.length; value5 = value4) { + int value6 = value4; + value4++; + methods[value6].accept(this); + } + Attribute[] attributes = javaClass.getAttributes(); + int value7; + for (int value8 = value7 = 0; value8 < attributes.length; value8 = value7) { + int value9 = value7; + value7++; + attributes[value9].accept(this); + } + javaClass.getConstantPool().accept(this); + this.stack.pop(); + } + + @Override + public void visitInnerClasses(InnerClasses innerClasses) { + this.stack.push(innerClasses); + innerClasses.accept(this.visitor); + InnerClass[] innerClasses2 = innerClasses.getInnerClasses(); + int value = 0; + for (int value2 = value; value2 < innerClasses2.length; value2 = value) { + int value3 = value; + value++; + innerClasses2[value3].accept(this); + } + this.stack.pop(); + } + + @Override + public void visitConstantUtf8(ConstantUtf8 constantUtf8) { + this.stack.push(constantUtf8); + constantUtf8.accept(this.visitor); + this.stack.pop(); + } + + @Override + public void visitConstantValue(ConstantValue constantValue) { + this.stack.push(constantValue); + constantValue.accept(this.visitor); + this.stack.pop(); + } + + @Override + public void visitField(Field field) { + this.stack.push(field); + field.accept(this.visitor); + Attribute[] attributes = field.getAttributes(); + int value = 0; + for (int value2 = value; value2 < attributes.length; value2 = value) { + int value3 = value; + value++; + attributes[value3].accept(this); + } + this.stack.pop(); + } + + @Override + public void visitConstantInteger(ConstantInteger constantInteger) { + this.stack.push(constantInteger); + constantInteger.accept(this.visitor); + this.stack.pop(); + } + + @Override + public void visitConstantLong(ConstantLong constantLong) { + this.stack.push(constantLong); + constantLong.accept(this.visitor); + this.stack.pop(); + } + + @Override + public void visitEnclosingMethod(EnclosingMethod enclosingMethod) { + this.stack.push(enclosingMethod); + enclosingMethod.accept(this.visitor); + this.stack.pop(); + } + + @Override + public void visitAnnotationEntry(AnnotationEntry annotationEntry) { + this.stack.push(annotationEntry); + annotationEntry.accept(this.visitor); + this.stack.pop(); + } + + @Override + public void visitAnnotationDefault(AnnotationDefault annotationDefault) { + this.stack.push(annotationDefault); + annotationDefault.accept(this.visitor); + this.stack.pop(); + } + + @Override + public void visitExceptionTable(ExceptionTable exceptionTable) { + this.stack.push(exceptionTable); + exceptionTable.accept(this.visitor); + this.stack.pop(); + } + + @Override + public void visitMethod(Method method) { + this.stack.push(method); + method.accept(this.visitor); + Attribute[] attributes = method.getAttributes(); + int value = 0; + for (int value2 = value; value2 < attributes.length; value2 = value) { + int value3 = value; + value++; + attributes[value3].accept(this); + } + this.stack.pop(); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/ElementValue.java b/src/main/java/com/allatori/lib/bcel/classfile/ElementValue.java new file mode 100644 index 0000000..7c2667d --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/ElementValue.java @@ -0,0 +1,149 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public abstract class ElementValue { + + public static final int COUNT = 68; + + public static final int COUNT2 = 101; + + public static final int COUNT3 = 83; + + public int type; + + public static final int COUNT4 = 70; + + public static final int COUNT5 = 66; + + public static final int COUNT6 = 67; + + public static final int COUNT7 = 74; + + public static final int COUNT8 = 90; + + public static final int COUNT9 = 91; + + public static final int COUNT10 = 115; + + public static final int COUNT11 = 73; + + public static final int COUNT12 = 64; + + public ConstantPool cpool; + + public static final int COUNT13 = 99; + + public int getType() { + return this.type; + } + + public static ElementValue createElementValue( + DataInputStream dataInputStream, ConstantPool constantPool) throws IOException { + byte value; + switch (value = dataInputStream.readByte()) { + case 64: + return new AnnotationElementValue( + 64, + AnnotationEntry.createAnnotationEntry(dataInputStream, constantPool, false), + constantPool); + case 65: + case 69: + case 71: + case 72: + case 75: + case 76: + case 77: + case 78: + case 79: + case 80: + case 81: + case 82: + case 84: + case 85: + case 86: + case 87: + case 88: + case 89: + case 92: + case 93: + case 94: + case 95: + case 96: + case 97: + case 98: + case 100: + case 102: + case 103: + case 104: + case 105: + case 106: + case 107: + case 108: + case 109: + case 110: + case 111: + case 112: + case 113: + case 114: + default: + throw new RuntimeException(("Unexpected element value kind in annotation: " + value)); + case 66: + return new SimpleElementValue(66, dataInputStream.readUnsignedShort(), constantPool); + case 67: + return new SimpleElementValue(67, dataInputStream.readUnsignedShort(), constantPool); + case 68: + return new SimpleElementValue(68, dataInputStream.readUnsignedShort(), constantPool); + case 70: + return new SimpleElementValue(70, dataInputStream.readUnsignedShort(), constantPool); + case 73: + return new SimpleElementValue(73, dataInputStream.readUnsignedShort(), constantPool); + case 74: + return new SimpleElementValue(74, dataInputStream.readUnsignedShort(), constantPool); + case 83: + return new SimpleElementValue(83, dataInputStream.readUnsignedShort(), constantPool); + case 90: + return new SimpleElementValue(90, dataInputStream.readUnsignedShort(), constantPool); + case 91: + int value2; + ElementValue[] elementValues = + new ElementValue[value2 = dataInputStream.readUnsignedShort()]; + int value3; + for (int value4 = value3 = 0; value4 < value2; value4 = value3) { + ElementValue elementValue = createElementValue(dataInputStream, constantPool); + int value5 = value3; + value3++; + elementValues[value5] = elementValue; + } + return new ArrayElementValue(91, elementValues, constantPool); + case 99: + return new ClassElementValue(99, dataInputStream.readUnsignedShort(), constantPool); + case 101: + return new EnumElementValue( + 101, + dataInputStream.readUnsignedShort(), + dataInputStream.readUnsignedShort(), + constantPool); + case 115: + return new SimpleElementValue(115, dataInputStream.readUnsignedShort(), constantPool); + } + } + + public abstract void dump(DataOutputStream dataOutputStream) throws IOException; + + public String createText() { + StringBuffer stringBuffer = new StringBuffer(); + stringBuffer.append(this.getText()); + return stringBuffer.toString(); + } + + public abstract String getText(); + + public ElementValue(int type, ConstantPool constantPool) { + super(); + this.type = type; + this.cpool = constantPool; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/ElementValuePair.java b/src/main/java/com/allatori/lib/bcel/classfile/ElementValuePair.java new file mode 100644 index 0000000..0d25465 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/ElementValuePair.java @@ -0,0 +1,45 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataOutputStream; +import java.io.IOException; + +public class ElementValuePair { + + public ConstantPool constantPool; + + public ElementValue elementValue; + + public int elementNameIndex; + + public int getNameIndex() { + return this.elementNameIndex; + } + + public void dump(DataOutputStream dataOutputStream) throws IOException { + dataOutputStream.writeShort(this.elementNameIndex); + this.elementValue.dump(dataOutputStream); + } + + public String createText() { + StringBuffer stringBuffer = new StringBuffer(); + stringBuffer.append(this.getText()).append("=").append(this.getValue().createText()); + return stringBuffer.toString(); + } + + public final ElementValue getValue() { + return this.elementValue; + } + + public String getText() { + return ((ConstantUtf8) this.constantPool.getConstant(this.elementNameIndex, (byte) 1)) + .getBytes(); + } + + public ElementValuePair( + int elementNameIndex, ElementValue elementValue2, ConstantPool constantPool2) { + super(); + this.elementValue = elementValue2; + this.elementNameIndex = elementNameIndex; + this.constantPool = constantPool2; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/EmptyVisitor.java b/src/main/java/com/allatori/lib/bcel/classfile/EmptyVisitor.java new file mode 100644 index 0000000..3b277ea --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/EmptyVisitor.java @@ -0,0 +1,119 @@ +package com.allatori.lib.bcel.classfile; + +public class EmptyVisitor implements Visitor { + + @Override + public void visitConstantFloat(ConstantFloat constantFloat) {} + + @Override + public void visitLineNumberTable(LineNumberTable lineNumberTable) {} + + @Override + public void visitInnerClasses(InnerClasses innerClasses) {} + + @Override + public void visitAnnotationDefault(AnnotationDefault annotationDefault) {} + + @Override + public void visitInnerClass(InnerClass innerClass) {} + + @Override + public void visitConstantMethodref(ConstantMethodref constantMethodref) {} + + @Override + public void visitDeprecated(Deprecated deprecated) {} + + @Override + public void visitConstantInterfaceMethodref( + ConstantInterfaceMethodref constantInterfaceMethodref) {} + + @Override + public void visitSourceFile(SourceFile sourceFile) {} + + @Override + public void visitExceptionTable(ExceptionTable exceptionTable) {} + + @Override + public void visitAnnotationEntry(AnnotationEntry annotationEntry) {} + + @Override + public void visitUnknown(Unknown unknown) {} + + @Override + public void visitConstantString(ConstantString constantString) {} + + @Override + public void visitLocalVariableTable(LocalVariableTable localVariableTable) {} + + @Override + public void visitConstantNameAndType(ConstantNameAndType constantNameAndType) {} + + @Override + public void visitCodeException(CodeException codeException) {} + + @Override + public void visitStackMapEntry(StackMapEntry stackMapEntry) {} + + @Override + public void visitConstantValue(ConstantValue constantValue) {} + + @Override + public void visitLineNumber(LineNumber lineNumber) {} + + @Override + public void visitLocalVariable(LocalVariable localVariable) {} + + @Override + public void visitLocalVariableTypeTable(LocalVariableTypeTable localVariableTypeTable) {} + + @Override + public void visitConstantLong(ConstantLong constantLong) {} + + @Override + public void visitStackMap(StackMap stackMap) {} + + @Override + public void visitMethod(Method method) {} + + @Override + public void visitParameterAnnotation(ParameterAnnotations parameterAnnotations) {} + + @Override + public void visitConstantDouble(ConstantDouble constantDouble) {} + + @Override + public void visitConstantFieldref(ConstantFieldref constantFieldref) {} + + @Override + public void visitConstantClass(ConstantClass constantClass) {} + + @Override + public void visitConstantInteger(ConstantInteger constantInteger) {} + + @Override + public void visitConstantUtf8(ConstantUtf8 constantUtf8) {} + + @Override + public void visitConstantPool(ConstantPool constantPool) {} + + @Override + public void visitAnnotation(Annotations annotations) {} + + @Override + public void visitCode(Code code) {} + + @Override + public void visitSignature(Signature signature) {} + + @Override + public void visitEnclosingMethod(EnclosingMethod enclosingMethod) {} + + @Override + public void visitSynthetic(Synthetic synthetic) {} + + @Override + public void visitField(Field field) {} + + @Override + public void visitJavaClass(JavaClass javaClass) {} +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/EnclosingMethod.java b/src/main/java/com/allatori/lib/bcel/classfile/EnclosingMethod.java new file mode 100644 index 0000000..24cad4c --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/EnclosingMethod.java @@ -0,0 +1,73 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public class EnclosingMethod extends Attribute { + + public int classIndex; + + public int methodIndex; + + public final int getMethodIndex() { + return this.methodIndex; + } + + @Override + public final void dump(DataOutputStream dataOutputStream) throws IOException { + super.dump(dataOutputStream); + dataOutputStream.writeShort(this.classIndex); + dataOutputStream.writeShort(this.methodIndex); + } + + public EnclosingMethod( + int value, int value2, int classIndex, int methodIndex, ConstantPool constantPool) { + super((byte) 18, value, value2, constantPool); + this.classIndex = classIndex; + this.methodIndex = methodIndex; + } + + public EnclosingMethod( + int value, int value2, DataInputStream dataInputStream, ConstantPool constantPool) + throws IOException { + this( + value, + value2, + dataInputStream.readUnsignedShort(), + dataInputStream.readUnsignedShort(), + constantPool); + } + + public final void setMethodIndex(int methodIndex) { + this.methodIndex = methodIndex; + } + + public final ConstantClass getEnclosingClass() { + return (ConstantClass) this.constant_pool.getConstant(this.classIndex, (byte) 7); + } + + public final ConstantNameAndType getEnclosingMethod() { + return this.methodIndex == 0 + ? null + : (ConstantNameAndType) this.constant_pool.getConstant(this.methodIndex, (byte) 12); + } + + public final int getClassIndex() { + return this.classIndex; + } + + @Override + public void accept(Visitor visitor) { + visitor.visitEnclosingMethod(this); + } + + public final void setClassIndex(int classIndex) { + this.classIndex = classIndex; + } + + @Override + public Attribute copy(ConstantPool constantPool) { + throw new RuntimeException("Not implemented yet!"); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/EnumElementValue.java b/src/main/java/com/allatori/lib/bcel/classfile/EnumElementValue.java new file mode 100644 index 0000000..b4726ea --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/EnumElementValue.java @@ -0,0 +1,48 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataOutputStream; +import java.io.IOException; + +public class EnumElementValue extends ElementValue { + + public int valueIdx; + + public int typeIdx; + + public String getText2() { + return ((ConstantUtf8) this.cpool.getConstant(this.typeIdx, (byte) 1)).getBytes(); + } + + public EnumElementValue(int value, int typeIdx, int valueIdx, ConstantPool constantPool) { + super(value, constantPool); + if (value != 101) { + throw new RuntimeException("Only element values of type enum can be built with this ctor"); + } + this.typeIdx = typeIdx; + this.valueIdx = valueIdx; + } + + public int getValueIdx() { + return this.valueIdx; + } + + public int getTypeIdx() { + return this.typeIdx; + } + + @Override + public void dump(DataOutputStream dataOutputStream) throws IOException { + dataOutputStream.writeByte(this.type); + dataOutputStream.writeShort(this.typeIdx); + dataOutputStream.writeShort(this.valueIdx); + } + + public String getText3() { + return ((ConstantUtf8) this.cpool.getConstant(this.valueIdx, (byte) 1)).getBytes(); + } + + @Override + public String getText() { + return ((ConstantUtf8) this.cpool.getConstant(this.valueIdx, (byte) 1)).getBytes(); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/ExceptionTable.java b/src/main/java/com/allatori/lib/bcel/classfile/ExceptionTable.java new file mode 100644 index 0000000..bceeef6 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/ExceptionTable.java @@ -0,0 +1,103 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public final class ExceptionTable extends Attribute { + + public int number_of_exceptions; + + public int[] exception_index_table; + + public ExceptionTable(ExceptionTable exceptionTable) { + this( + exceptionTable.getName_index(), + exceptionTable.getLength(), + exceptionTable.getExceptionIndexTable(), + exceptionTable.getConstantPool()); + } + + @Override + public final void dump(DataOutputStream dataOutputStream) throws IOException { + int value = 0; + super.dump(dataOutputStream); + dataOutputStream.writeShort(this.number_of_exceptions); + for (int index = 0; value < this.number_of_exceptions; value = index) { + int value2 = index; + int[] values = this.exception_index_table; + index++; + dataOutputStream.writeShort(values[value2]); + } + } + + public final String[] getExceptionNames() { + String[] texts = new String[this.number_of_exceptions]; + int value; + for (int value2 = value = 0; value2 < this.number_of_exceptions; value2 = value) { + String text = + this.constant_pool + .createText(this.exception_index_table[value], (byte) 7) + .replace('/', '.'); + int value3 = value; + value++; + texts[value3] = text; + } + return texts; + } + + public final int[] getExceptionIndexTable() { + return this.exception_index_table; + } + + @Override + public Attribute copy(ConstantPool constantPool) { + ExceptionTable exceptionTable = (ExceptionTable) this.clone(); + if (this.exception_index_table != null) { + exceptionTable.exception_index_table = new int[this.exception_index_table.length]; + System.arraycopy( + this.exception_index_table, + 0, + exceptionTable.exception_index_table, + 0, + this.exception_index_table.length); + } + exceptionTable.constant_pool = constantPool; + return exceptionTable; + } + + public ExceptionTable( + int value, int value2, DataInputStream dataInputStream, ConstantPool constantPool) + throws IOException { + this(value, value2, (int[]) null, constantPool); + int value3 = 0; + this.number_of_exceptions = dataInputStream.readUnsignedShort(); + this.exception_index_table = new int[this.number_of_exceptions]; + for (int index = 0; value3 < this.number_of_exceptions; value3 = index) { + int[] values = this.exception_index_table; + int value4 = dataInputStream.readUnsignedShort(); + int value5 = index; + index++; + values[value5] = value4; + } + } + + public final void setExceptionIndexTable(int[] exception_index_table) { + this.exception_index_table = exception_index_table; + this.number_of_exceptions = exception_index_table == null ? 0 : exception_index_table.length; + } + + @Override + public void accept(Visitor visitor) { + visitor.visitExceptionTable(this); + } + + public final int getNumberOfExceptions() { + return this.number_of_exceptions; + } + + public ExceptionTable(int value, int value2, int[] values, ConstantPool constantPool) { + super((byte) 3, value, value2, constantPool); + this.setExceptionIndexTable(values); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/Field.java b/src/main/java/com/allatori/lib/bcel/classfile/Field.java new file mode 100644 index 0000000..7989ff4 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/Field.java @@ -0,0 +1,67 @@ +package com.allatori.lib.bcel.classfile; + +import com.allatori.lib.bcel.generic.Type; +import com.allatori.lib.bcel.util.BCELComparator; +import com.allatori.lib.bcel.util.comparator.FieldComparator; +import java.io.DataInputStream; +import java.io.IOException; + +public final class Field extends FieldOrMethod { + + public static BCELComparator _cmp = new FieldComparator(); + + public Field( + int value, int value2, int value3, Attribute[] attributes, ConstantPool constantPool) { + super(value, value2, value3, attributes, constantPool); + } + + public Field(DataInputStream dataInputStream, ConstantPool constantPool) + throws IOException, ClassFormatException { + super(dataInputStream, constantPool); + } + + public Type getType() { + return Type.getReturnType(this.getText2()); + } + + public final Field copy(ConstantPool constantPool) { + return (Field) this.copy_(constantPool); + } + + public final ConstantValue getConstantValue() { + int value; + for (int value2 = value = 0; value2 < this.count2; value2 = ++value) { + if (this.attributes[value].getTag() == 1) { + return (ConstantValue) this.attributes[value]; + } + } + return null; + } + + public static BCELComparator getComparator() { + return _cmp; + } + + @Override + public void accept(Visitor visitor) { + visitor.visitField(this); + } + + @Override + public boolean equals(Object result) { + return _cmp.equals(this, result); + } + + @Override + public int hashCode() { + return _cmp.hashCode(this); + } + + public static void setComparator(BCELComparator bCELComparator) { + _cmp = bCELComparator; + } + + public Field(Field field) { + super(field); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/FieldOrMethod.java b/src/main/java/com/allatori/lib/bcel/classfile/FieldOrMethod.java new file mode 100644 index 0000000..64d6bc2 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/FieldOrMethod.java @@ -0,0 +1,213 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.ArrayList; + +public abstract class FieldOrMethod extends AccessFlags implements Cloneable, Node { + + public boolean enabled; + + public AnnotationEntry[] annotationEntries; + + public int count; + + public String signatureAttributeString = null; + + public Attribute[] attributes; + + public boolean enabled2; + + public ConstantPool constant_pool; + + public int count2; + + public int count3; + + public final String getText() { + return ((ConstantUtf8) this.constant_pool.getConstant(this.count3, (byte) 1)).getBytes(); + } + + public FieldOrMethod() { + this.enabled = false; + this.enabled2 = true; + } + + public final int getCount() { + return this.count; + } + + public void update() { + if (this.enabled2) { + Attribute[] attributes = this.getAttributes(); + ArrayList values = new ArrayList(); + int value; + for (int value2 = value = 0; value2 < attributes.length; value2 = ++value) { + Attribute attribute; + if ((attribute = attributes[value]) instanceof Annotations) { + Annotations annotations = (Annotations) attribute; + int value3; + for (int value4 = value3 = 0; + value4 < annotations.getAnnotationEntries().length; + value4 = value3) { + AnnotationEntry[] annotationEntries2 = annotations.getAnnotationEntries(); + int value5 = value3; + value3++; + values.add(annotationEntries2[value5]); + } + } + } + this.annotationEntries = + (AnnotationEntry[]) values.toArray(new AnnotationEntry[values.size()]); + this.enabled2 = false; + } + } + + public final int getCount3() { + return this.count3; + } + + public FieldOrMethod(DataInputStream dataInputStream, ConstantPool constantPool) + throws IOException { + this( + dataInputStream.readUnsignedShort(), + dataInputStream.readUnsignedShort(), + dataInputStream.readUnsignedShort(), + null, + constantPool); + this.count2 = dataInputStream.readUnsignedShort(); + this.attributes = new Attribute[this.count2]; + int value; + for (int value2 = value = 0; value2 < this.count2; value2 = value) { + Attribute[] attributes2 = this.attributes; + Attribute attribute = Attribute.readAttribute(dataInputStream, constantPool); + int value3 = value; + value++; + attributes2[value3] = attribute; + } + } + + public FieldOrMethod( + int access_flags, int count3, int count, Attribute[] attributes, ConstantPool constantPool) { + super(); + this.signatureAttributeString = null; + this.enabled = false; + this.enabled2 = true; + this.access_flags = access_flags; + this.count3 = count3; + this.count = count; + this.constant_pool = constantPool; + this.setAttributes(attributes); + } + + public void processAnnotationEntry(AnnotationEntry annotationEntry) { + this.update(); + AnnotationEntry[] annotationEntrys; + int value; + AnnotationEntry[] annotationEntrys2 = + annotationEntrys = new AnnotationEntry[(value = this.annotationEntries.length) + 1]; + System.arraycopy(this.annotationEntries, 0, annotationEntrys, 0, value); + annotationEntrys2[value] = annotationEntry; + this.annotationEntries = annotationEntrys2; + } + + public FieldOrMethod copy_(ConstantPool constantPool) { + FieldOrMethod fieldOrMethod = null; + FieldOrMethod fieldOrMethod2; + label22: + { + try { + fieldOrMethod = (FieldOrMethod) this.clone(); + } catch (CloneNotSupportedException cloneNotSupportedException) { + fieldOrMethod2 = fieldOrMethod; + break label22; + } + fieldOrMethod2 = fieldOrMethod; + } + fieldOrMethod2.constant_pool = this.constant_pool; + fieldOrMethod.attributes = new Attribute[this.count2]; + int value; + for (int value2 = value = 0; value2 < this.count2; value2 = value) { + Attribute[] attributes2 = fieldOrMethod.attributes; + Attribute attribute = this.attributes[value].copy(this.constant_pool); + int value3 = value; + value++; + attributes2[value3] = attribute; + } + return fieldOrMethod; + } + + public final ConstantPool getConstantPool() { + return this.constant_pool; + } + + public final String getText2() { + return ((ConstantUtf8) this.constant_pool.getConstant(this.count, (byte) 1)).getBytes(); + } + + public FieldOrMethod(FieldOrMethod fieldOrMethod) { + this( + fieldOrMethod.getAccess_flags2(), + fieldOrMethod.getCount3(), + fieldOrMethod.getCount(), + fieldOrMethod.getAttributes(), + fieldOrMethod.getConstantPool()); + } + + public AnnotationEntry[] getAnnotationEntries() { + this.update(); + return this.annotationEntries; + } + + public final void setCount3(int count3) { + this.count3 = count3; + } + + public final void setConstantPool(ConstantPool constantPool) { + this.constant_pool = constantPool; + } + + public final void dump(DataOutputStream dataOutputStream) throws IOException { + int value = 0; + dataOutputStream.writeShort(this.access_flags); + dataOutputStream.writeShort(this.count3); + dataOutputStream.writeShort(this.count); + dataOutputStream.writeShort(this.count2); + for (int index = 0; value < this.count2; value = index) { + int value2 = index; + Attribute[] attributes2 = this.attributes; + index++; + attributes2[value2].dump(dataOutputStream); + } + } + + public final void setAttributes(Attribute[] attributes2) { + this.attributes = attributes2; + this.count2 = attributes2 == null ? 0 : attributes2.length; + } + + public final void setCount(int count) { + this.count = count; + } + + public final Attribute[] getAttributes() { + return this.attributes; + } + + public final String getText3() { + if (!this.enabled) { + byte value = 0; + int value2 = 0; + for (byte value3 = value; value3 == 0 && value2 < this.count2; value3 = value) { + if (this.attributes[value2] instanceof Signature) { + this.signatureAttributeString = ((Signature) this.attributes[value2]).getText(); + value = 1; + } + value2++; + } + this.enabled = true; + } + return this.signatureAttributeString; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/InnerClass.java b/src/main/java/com/allatori/lib/bcel/classfile/InnerClass.java new file mode 100644 index 0000000..f76870e --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/InnerClass.java @@ -0,0 +1,121 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.Serializable; + +public final class InnerClass implements Cloneable, Node, Serializable { + + public int outer_class_index; + + public int inner_access_flags; + + public int inner_class_index; + + public int inner_name_index; + + public InnerClass(InnerClass innerClass) { + this( + innerClass.getInner_class_index(), + innerClass.getOuter_class_index(), + innerClass.getInner_name_index(), + innerClass.getInner_access_flags()); + } + + public InnerClass( + int inner_class_index, int outer_class_index, int inner_name_index, int inner_access_flags) { + super(); + this.inner_class_index = inner_class_index; + this.outer_class_index = outer_class_index; + this.inner_name_index = inner_name_index; + this.inner_access_flags = inner_access_flags; + } + + public final int getOuter_class_index() { + return this.outer_class_index; + } + + public final void setInner_class_index(int inner_class_index) { + this.inner_class_index = inner_class_index; + } + + public final int getInner_class_index() { + return this.inner_class_index; + } + + public final void setOuter_class_index(int outer_class_index) { + this.outer_class_index = outer_class_index; + } + + public InnerClass(DataInputStream dataInputStream) throws IOException { + this( + dataInputStream.readUnsignedShort(), + dataInputStream.readUnsignedShort(), + dataInputStream.readUnsignedShort(), + dataInputStream.readUnsignedShort()); + } + + public final void setInner_access_flags(int inner_access_flags) { + this.inner_access_flags = inner_access_flags; + } + + public final int getInner_access_flags() { + return this.inner_access_flags; + } + + public InnerClass copy() { + try { + return (InnerClass) this.clone(); + } catch (CloneNotSupportedException cloneNotSupportedException) { + return null; + } + } + + @Override + public void accept(Visitor visitor) { + visitor.visitInnerClass(this); + } + + public final void dump(DataOutputStream dataOutputStream) throws IOException { + dataOutputStream.writeShort(this.inner_class_index); + dataOutputStream.writeShort(this.outer_class_index); + dataOutputStream.writeShort(this.inner_name_index); + dataOutputStream.writeShort(this.inner_access_flags); + } + + public final int getInner_name_index() { + return this.inner_name_index; + } + + public final void setInner_name_index(int inner_name_index) { + this.inner_name_index = inner_name_index; + } + + public final String toString(ConstantPool constantPool) { + String text = Utility.getText(constantPool.createText(this.inner_class_index, (byte) 7)); + String text2; + InnerClass innerClass; + if (this.outer_class_index != 0) { + text2 = Utility.getText(constantPool.createText(this.outer_class_index, (byte) 7)); + innerClass = this; + } else { + text2 = ""; + innerClass = this; + } + String text3; + if (innerClass.inner_name_index != 0) { + text3 = ((ConstantUtf8) constantPool.getConstant(this.inner_name_index, (byte) 1)).getBytes(); + innerClass = this; + } else { + text3 = ""; + innerClass = this; + } + String text4; + String text5 = + (text4 = Utility.accessToString(innerClass.inner_access_flags, true)).equals("") + ? "" + : ("" + text4 + " "); + return "InnerClass:" + text5 + text + "(\"" + text2 + "\", \"" + text3 + "\")"; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/InnerClasses.java b/src/main/java/com/allatori/lib/bcel/classfile/InnerClasses.java new file mode 100644 index 0000000..504a6e0 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/InnerClasses.java @@ -0,0 +1,85 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public final class InnerClasses extends Attribute { + + public int number_of_classes; + + public InnerClass[] inner_classes; + + @Override + public final void dump(DataOutputStream dataOutputStream) throws IOException { + int value = 0; + super.dump(dataOutputStream); + dataOutputStream.writeShort(this.number_of_classes); + for (int index = 0; value < this.number_of_classes; value = index) { + int value2 = index; + InnerClass[] innerClasss = this.inner_classes; + index++; + innerClasss[value2].dump(dataOutputStream); + } + } + + @Override + public void accept(Visitor visitor) { + visitor.visitInnerClasses(this); + } + + public final InnerClass[] getInnerClasses() { + return this.inner_classes; + } + + @Override + public Attribute copy(ConstantPool constantPool) { + InnerClasses innerClasses; + (innerClasses = (InnerClasses) this.clone()).inner_classes = + new InnerClass[this.number_of_classes]; + int value; + for (int value2 = value = 0; value2 < this.number_of_classes; value2 = value) { + InnerClass[] innerClasss = innerClasses.inner_classes; + InnerClass innerClass = this.inner_classes[value].copy(); + int value3 = value; + value++; + innerClasss[value3] = innerClass; + } + innerClasses.constant_pool = constantPool; + return innerClasses; + } + + public InnerClasses(int value, int value2, InnerClass[] innerClasss, ConstantPool constantPool) { + super((byte) 6, value, value2, constantPool); + this.setInnerClasses(innerClasss); + } + + public InnerClasses( + int value, int value2, DataInputStream dataInputStream, ConstantPool constantPool) + throws IOException { + this(value, value2, (InnerClass[]) null, constantPool); + this.number_of_classes = dataInputStream.readUnsignedShort(); + this.inner_classes = new InnerClass[this.number_of_classes]; + int value3; + for (int value4 = value3 = 0; value4 < this.number_of_classes; value4 = value3) { + InnerClass[] innerClasss = this.inner_classes; + InnerClass innerClass = new InnerClass(dataInputStream); + int value5 = value3; + value3++; + innerClasss[value5] = innerClass; + } + } + + public InnerClasses(InnerClasses innerClasses) { + this( + innerClasses.getName_index(), + innerClasses.getLength(), + innerClasses.getInnerClasses(), + innerClasses.getConstantPool()); + } + + public final void setInnerClasses(InnerClass[] innerClasss) { + this.inner_classes = innerClasss; + this.number_of_classes = innerClasss == null ? 0 : innerClasss.length; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/JavaClass.java b/src/main/java/com/allatori/lib/bcel/classfile/JavaClass.java new file mode 100644 index 0000000..de2636e --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/JavaClass.java @@ -0,0 +1,705 @@ +package com.allatori.lib.bcel.classfile; + +import com.allatori.lib.bcel.generic.Type; +import com.allatori.lib.bcel.util.BCELComparator; +import com.allatori.lib.bcel.util.ClassQueue; +import com.allatori.lib.bcel.util.Repository; +import com.allatori.lib.bcel.util.SyntheticRepository; +import com.allatori.lib.bcel.util.comparator.JavaClassComparator; +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.StringTokenizer; +import java.util.TreeSet; + +public class JavaClass extends AccessFlags implements Cloneable, Node, Comparable { + + public AnnotationEntry[] annotations; + + public String[] interface_names; + + public String text; + + public byte source; + + public String text2; + + public boolean enabled; + + public boolean enabled2; + + public String text3; + + public int count; + + public static boolean debug = false; + + static { + debug = Boolean.getBoolean("JavaClass.debug"); + String text; + if ((text = System.getProperty("file.separator")) != null) { + try { + character = text.charAt(0); + } catch (StringIndexOutOfBoundsException stringIndexOutOfBoundsException) { + } + } + } + + public static char character = '/'; + + public static BCELComparator bcelComparator = new JavaClassComparator(); + + public int count2; + + public boolean enabled3; + + public int count3; + + public Method[] methods; + + public String text4; + + public Field[] fields; + + public boolean enabled4; + + public int count4; + + public String text5; + + public static final byte HEAP = 1; + + public ConstantPool constant_pool; + + public static final byte ZIP = 3; + + public Attribute[] attributes; + + public static final byte FILE = 2; + + public int[] interfaces; + + public transient Repository repository; + + @Override + public boolean equals(Object result) { + return bcelComparator.equals(this, result); + } + + public ConstantPool getConstantPool() { + return this.constant_pool; + } + + public void setCount4(int count4) { + this.count4 = count4; + } + + public JavaClass getSuperClass() throws ClassNotFoundException { + return "java.lang.Object".equals(this.getText2()) + ? null + : this.repository.getJavaClass2(this.getText5()); + } + + public final boolean isEnabled16() { + return (this.access_flags & 32) != 0; + } + + public String[] getInterfaceNames() { + return this.interface_names; + } + + public void setCount(int count) { + this.count = count; + } + + public void setText2(String text2) { + this.text2 = text2; + } + + public JavaClass( + int count, + int count2, + String text3, + int count3, + int count4, + int access_flags, + ConstantPool constantPool, + int[] interfaces, + Field[] fields2, + Method[] methods2, + Attribute[] attributes2, + byte source) { + super(); + JavaClass javaClass; + this.text = ""; + this.source = 1; + this.enabled = false; + this.enabled2 = false; + this.enabled4 = false; + this.enabled3 = true; + this.repository = SyntheticRepository.getInstance(); + if (interfaces == null) { + interfaces = new int[0]; + } + if (attributes2 == null) { + attributes2 = new Attribute[0]; + } + if (fields2 == null) { + fields2 = new Field[0]; + } + if (methods2 == null) { + methods2 = new Method[0]; + } + this.count = count; + this.count2 = count2; + this.text3 = text3; + this.count3 = count3; + this.count4 = count4; + this.access_flags = access_flags; + this.constant_pool = constantPool; + this.interfaces = interfaces; + this.fields = fields2; + this.methods = methods2; + this.attributes = attributes2; + this.enabled3 = true; + this.source = source; + int value7; + int value8 = value7 = 0; + while (true) { + if (value8 >= attributes2.length) { + javaClass = this; + break; + } + if (attributes2[value7] instanceof SourceFile) { + this.text = ((SourceFile) attributes2[value7]).getText(); + javaClass = this; + break; + } + value8 = ++value7; + } + javaClass.text2 = constantPool.createText(count, (byte) 7); + this.text2 = Utility.getText(this.text2, false); + int value9; + if ((value9 = this.text2.lastIndexOf(46)) < 0) { + this.text4 = ""; + value8 = count2; + } else { + this.text4 = this.text2.substring(0, value9); + value8 = count2; + } + JavaClass javaClass2; + if (value8 > 0) { + javaClass2 = this; + this.text5 = constantPool.createText(count2, (byte) 7); + this.text5 = Utility.getText(this.text5, false); + } else { + javaClass2 = this; + this.text5 = "java.lang.Object"; + } + javaClass2.interface_names = new String[interfaces.length]; + int value10; + for (int value11 = value10 = 0; value11 < interfaces.length; value11 = value10) { + String text7 = constantPool.createText(interfaces[value10], (byte) 7); + String[] texts = this.interface_names; + String text8 = Utility.getText(text7, false); + int value12 = value10; + value10++; + texts[value12] = text8; + } + } + + public int getCount3() { + return this.count3; + } + + public void setCount2(int count2) { + this.count2 = count2; + } + + public JavaClass[] createJavaClasss() throws ClassNotFoundException { + ArrayList values = new ArrayList(); + JavaClass javaClass; + for (JavaClass javaClass2 = javaClass = this.getSuperClass(); + javaClass2 != null; + javaClass2 = javaClass) { + values.add(javaClass); + javaClass = javaClass.getSuperClass(); + } + return (JavaClass[]) values.toArray(new JavaClass[values.size()]); + } + + @Override + public int hashCode() { + return bcelComparator.hashCode(this); + } + + public void dump(File file) throws IOException { + String text; + if ((text = file.getParent()) != null) { + new File(text).mkdirs(); + } + DataOutputStream dataOutputStream = null; + boolean matches = false; + try { + matches = true; + dataOutputStream = new DataOutputStream(new FileOutputStream(file)); + this.dump(dataOutputStream); + matches = false; + } finally { + if (matches) { + if (dataOutputStream != null) { + dataOutputStream.close(); + } + } + } + dataOutputStream.close(); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitJavaClass(this); + } + + public Method getMethod(java.lang.reflect.Method method) { + int value; + for (int value2 = value = 0; value2 < this.methods.length; value2 = ++value) { + Method method2 = this.methods[value]; + if (method.getName().equals(method2.getText()) + && method.getModifiers() == method2.getAccess_flags() + && Type.getSignature(method).equals(method2.getText2())) { + return method2; + } + } + return null; + } + + public void setConstantPool(ConstantPool constantPool) { + this.constant_pool = constantPool; + } + + public String getText() { + return this.text; + } + + public final boolean isEnabled17() { + return (this.access_flags & 512) == 0; + } + + public void setRepository(Repository repository2) { + this.repository = repository2; + } + + public void setText5(String text5) { + this.text5 = text5; + } + + public JavaClass[] getJavaClasss() throws ClassNotFoundException { + String[] texts; + JavaClass[] javaClasss = new JavaClass[(texts = this.getInterfaceNames()).length]; + int value; + for (int value2 = value = 0; value2 < texts.length; value2 = value) { + JavaClass javaClass2 = this.repository.getJavaClass2(texts[value]); + int value3 = value; + value++; + javaClasss[value3] = javaClass2; + } + return javaClasss; + } + + public final void computeNestedTypeStatus() { + if (!this.enabled4) { + int value; + for (int value2 = value = 0; value2 < this.attributes.length; value2 = ++value) { + if (this.attributes[value] instanceof InnerClasses) { + InnerClass[] innerClasses = ((InnerClasses) this.attributes[value]).getInnerClasses(); + int value3; + for (int value4 = value3 = 0; value4 < innerClasses.length; value4 = ++value3) { + byte value5 = 0; + if (Utility.getText( + this.constant_pool.createText( + innerClasses[value3].getInner_class_index(), (byte) 7)) + .equals(this.getText2())) { + value5 = 1; + } + if (value5 != 0) { + this.enabled2 = true; + if (innerClasses[value3].getInner_name_index() == 0) { + this.enabled = true; + } + } + } + } + } + this.enabled4 = true; + } + } + + public boolean matchesJavaClass(JavaClass javaClass) throws ClassNotFoundException { + if (!javaClass.isEnabled5()) { + throw new IllegalArgumentException(("" + javaClass.getText2() + " is no interface")); + } + if (this.equals(javaClass)) { + return true; + } + JavaClass[] javaClasss = this.createJavaClasss2(); + int value; + for (int value2 = value = 0; value2 < javaClasss.length; value2 = ++value) { + if (javaClasss[value].equals(javaClass)) { + return true; + } + } + return false; + } + + public void setCount3(int count3) { + this.count3 = count3; + } + + public String getText3() { + return this.text3; + } + + public JavaClass( + int value, + int value2, + String text, + int value3, + int value4, + int value5, + ConstantPool constantPool, + int[] values, + Field[] fields, + Method[] methods, + Attribute[] attributes) { + this( + value, + value2, + text, + value3, + value4, + value5, + constantPool, + values, + fields, + methods, + attributes, + (byte) 1); + } + + public static void setComparator(BCELComparator bCELComparator) { + bcelComparator = bCELComparator; + } + + public byte[] getBytes() { + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + DataOutputStream dataOutputStream = new DataOutputStream(byteArrayOutputStream); + label86: + { + try { + try { + this.dump(dataOutputStream); + break label86; + } catch (IOException oException) { + oException.printStackTrace(); + } + } catch (Throwable throwable) { + try { + dataOutputStream.close(); + } catch (IOException oException2) { + oException2.printStackTrace(); + throw throwable; + } + throw throwable; + } + try { + dataOutputStream.close(); + } catch (IOException oException3) { + oException3.printStackTrace(); + return byteArrayOutputStream.toByteArray(); + } + return byteArrayOutputStream.toByteArray(); + } + try { + dataOutputStream.close(); + } catch (IOException oException4) { + oException4.printStackTrace(); + return byteArrayOutputStream.toByteArray(); + } + return byteArrayOutputStream.toByteArray(); + } + + public void setText(String text) { + this.text = text; + } + + public Repository getRepository() { + return this.repository; + } + + public void setInterfaces(int[] interfaces) { + this.interfaces = interfaces; + } + + public void setInterfaceNames(String[] texts) { + this.interface_names = texts; + } + + public void dump(DataOutputStream dataOutputStream) throws IOException { + dataOutputStream.writeInt(-889275714); + dataOutputStream.writeShort(this.count4); + dataOutputStream.writeShort(this.count3); + this.constant_pool.dump(dataOutputStream); + dataOutputStream.writeShort(this.access_flags); + dataOutputStream.writeShort(this.count); + dataOutputStream.writeShort(this.count2); + dataOutputStream.writeShort(this.interfaces.length); + int value; + for (int value2 = value = 0; value2 < this.interfaces.length; value2 = value) { + int value3 = value; + int[] values = this.interfaces; + value++; + dataOutputStream.writeShort(values[value3]); + } + dataOutputStream.writeShort(this.fields.length); + int value4; + for (int value5 = value4 = 0; value5 < this.fields.length; value5 = value4) { + int value6 = value4; + Field[] fields2 = this.fields; + value4++; + fields2[value6].dump(dataOutputStream); + } + dataOutputStream.writeShort(this.methods.length); + int value7; + for (int value8 = value7 = 0; value8 < this.methods.length; value8 = value7) { + int value9 = value7; + Method[] methods2 = this.methods; + value7++; + methods2[value9].dump(dataOutputStream); + } + if (this.attributes != null) { + dataOutputStream.writeShort(this.attributes.length); + int value10; + for (int value11 = value10 = 0; value11 < this.attributes.length; value11 = value10) { + int value12 = value10; + Attribute[] attributes2 = this.attributes; + value10++; + attributes2[value12].dump(dataOutputStream); + } + } else { + dataOutputStream.writeShort(0); + } + dataOutputStream.flush(); + } + + public int getCount() { + return this.count; + } + + public void setFields(Field[] fields2) { + this.fields = fields2; + } + + public Method[] getMethods() { + return this.methods; + } + + public int getCount4() { + return this.count4; + } + + public int[] getInterfaceIndices() { + return this.interfaces; + } + + public static final String indent(Object result) { + StringTokenizer stringTokenizer = new StringTokenizer(result.toString(), "\n"); + StringBuffer stringBuffer = new StringBuffer(); + StringTokenizer stringTokenizer2 = stringTokenizer; + while (stringTokenizer2.hasMoreTokens()) { + StringBuffer stringBuffer2 = stringBuffer.append("\t"); + stringTokenizer2 = stringTokenizer; + stringBuffer2.append(stringTokenizer.nextToken()).append("\n"); + } + return stringBuffer.toString(); + } + + public String getText4() { + return this.text4; + } + + public final boolean isEnabled18() { + this.computeNestedTypeStatus(); + return this.enabled; + } + + public JavaClass[] createJavaClasss2() throws ClassNotFoundException { + ClassQueue classQueue = new ClassQueue(); + TreeSet treeSet = new TreeSet(); + classQueue.enqueue(this); + while (!classQueue.empty()) { + JavaClass javaClass; + JavaClass javaClass2 = javaClass = classQueue.dequeue(); + JavaClass superClass = javaClass2.getSuperClass(); + JavaClass[] javaClasss = javaClass2.getJavaClasss(); + if (javaClass2.isEnabled5()) { + treeSet.add(javaClass); + } else if (superClass != null) { + classQueue.enqueue(superClass); + } + int value; + for (int value2 = value = 0; value2 < javaClasss.length; value2 = value) { + int value3 = value; + value++; + classQueue.enqueue(javaClasss[value3]); + } + } + return (JavaClass[]) treeSet.toArray(new JavaClass[treeSet.size()]); + } + + public static BCELComparator getComparator() { + return bcelComparator; + } + + public String getText5() { + return this.text5; + } + + public void processText(String text) throws IOException { + this.dump(new File(text)); + } + + public static final void Debug(String text) { + if (debug) { + System.out.println(text); + } + } + + public final byte getSource() { + return this.source; + } + + public Field[] getFields() { + return this.fields; + } + + public JavaClass copy() { + JavaClass javaClass = null; + try { + javaClass = (JavaClass) this.clone(); + javaClass.constant_pool = this.constant_pool.copy(); + javaClass.interfaces = (int[]) this.interfaces.clone(); + javaClass.interface_names = (String[]) this.interface_names.clone(); + javaClass.fields = new Field[this.fields.length]; + int value; + for (int value2 = value = 0; value2 < this.fields.length; value2 = value) { + Field[] fields2 = javaClass.fields; + Field field = this.fields[value].copy(javaClass.constant_pool); + int value3 = value; + value++; + fields2[value3] = field; + } + javaClass.methods = new Method[this.methods.length]; + int value4; + for (int value5 = value4 = 0; value5 < this.methods.length; value5 = value4) { + Method[] methods2 = javaClass.methods; + Method method = this.methods[value4].copy(javaClass.constant_pool); + int value6 = value4; + value4++; + methods2[value6] = method; + } + javaClass.attributes = new Attribute[this.attributes.length]; + int value7 = 0; + while (value7 < this.attributes.length) { + Attribute[] attributes2 = javaClass.attributes; + Attribute attribute = this.attributes[value7].copy(javaClass.constant_pool); + int value8 = value7; + value7++; + attributes2[value8] = attribute; + } + } catch (CloneNotSupportedException cloneNotSupportedException) { + } + return javaClass; + } + + public Attribute[] getAttributes() { + return this.attributes; + } + + public void dump(OutputStream outputStream) throws IOException { + this.dump(new DataOutputStream(outputStream)); + } + + public String getText2() { + return this.text2; + } + + @Override + public int compareTo(Object result) { + return this.getText2().compareTo(((JavaClass) result).getText2()); + } + + public void setMethods(Method[] methods2) { + this.methods = methods2; + } + + public int getCount2() { + return this.count2; + } + + public void setAttributes(Attribute[] attributes2) { + this.attributes = attributes2; + } + + public void setText3(String text3) { + this.text3 = text3; + } + + public final boolean isEnabled22() { + this.computeNestedTypeStatus(); + return this.enabled2; + } + + public AnnotationEntry[] getAnnotationEntries() { + if (this.enabled3) { + Attribute[] attributes = this.getAttributes(); + ArrayList values = new ArrayList(); + int value; + for (int value2 = value = 0; value2 < attributes.length; value2 = ++value) { + Attribute attribute; + if ((attribute = attributes[value]) instanceof Annotations) { + Annotations annotations2 = (Annotations) attribute; + int value3; + for (int value4 = value3 = 0; + value4 < annotations2.getAnnotationEntries().length; + value4 = value3) { + AnnotationEntry[] annotationEntries = annotations2.getAnnotationEntries(); + int value5 = value3; + value3++; + values.add(annotationEntries[value5]); + } + } + } + this.annotations = (AnnotationEntry[]) values.toArray(new AnnotationEntry[values.size()]); + this.enabled3 = false; + } + return this.annotations; + } + + public final boolean matchesJavaClass2(JavaClass javaClass) throws ClassNotFoundException { + if (this.equals(javaClass)) { + return true; + } + JavaClass[] javaClasss = this.createJavaClasss(); + int value; + for (int value2 = value = 0; value2 < javaClasss.length; value2 = ++value) { + if (javaClasss[value].equals(javaClass)) { + return true; + } + } + return javaClass.isEnabled5() ? this.matchesJavaClass(javaClass) : false; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/LineNumber.java b/src/main/java/com/allatori/lib/bcel/classfile/LineNumber.java new file mode 100644 index 0000000..2133e0c --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/LineNumber.java @@ -0,0 +1,61 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.Serializable; + +public final class LineNumber implements Cloneable, Node, Serializable { + + public int start_pc; + + public int line_number; + + public final void setLine_number(int line_number) { + this.line_number = line_number; + } + + public LineNumber(DataInputStream dataInputStream) throws IOException { + this(dataInputStream.readUnsignedShort(), dataInputStream.readUnsignedShort()); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitLineNumber(this); + } + + public final int getLine_number() { + return this.line_number; + } + + public LineNumber(int start_pc, int line_number) { + super(); + this.start_pc = start_pc; + this.line_number = line_number; + } + + public final void dump(DataOutputStream dataOutputStream) throws IOException { + dataOutputStream.writeShort(this.start_pc); + dataOutputStream.writeShort(this.line_number); + } + + public LineNumber copy() { + try { + return (LineNumber) this.clone(); + } catch (CloneNotSupportedException cloneNotSupportedException) { + return null; + } + } + + public LineNumber(LineNumber lineNumber) { + this(lineNumber.getStart_pc(), lineNumber.getLine_number()); + } + + public final int getStart_pc() { + return this.start_pc; + } + + public final void setStart_pc(int start_pc) { + this.start_pc = start_pc; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/LineNumberTable.java b/src/main/java/com/allatori/lib/bcel/classfile/LineNumberTable.java new file mode 100644 index 0000000..3d2bc0b --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/LineNumberTable.java @@ -0,0 +1,120 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public final class LineNumberTable extends Attribute { + + public LineNumber[] line_number_table; + + public int line_number_table_length; + + @Override + public void accept(Visitor visitor) { + visitor.visitLineNumberTable(this); + } + + @Override + public final void dump(DataOutputStream dataOutputStream) throws IOException { + int value = 0; + super.dump(dataOutputStream); + dataOutputStream.writeShort(this.line_number_table_length); + for (int index = 0; value < this.line_number_table_length; value = index) { + int value2 = index; + LineNumber[] lineNumbers = this.line_number_table; + index++; + lineNumbers[value2].dump(dataOutputStream); + } + } + + public int getSourceLine(int value) { + int value2 = 0; + int value3; + if ((value3 = this.line_number_table_length - 1) < 0) { + return -1; + } + int value4 = -1; + int value5 = -1; + do { + int value6 = (value2 + value3) / 2; + int value7; + if ((value7 = this.line_number_table[value6].getStart_pc()) == value) { + return this.line_number_table[value6].getLine_number(); + } + int value8; + if (value < value7) { + value3 = value6 - 1; + value8 = value7; + } else { + value2 = value6 + 1; + value8 = value7; + } + if (value8 < value && value7 > value5) { + value5 = value7; + value4 = value6; + } + } while (value2 <= value3); + return value4 < 0 ? -1 : this.line_number_table[value4].getLine_number(); + } + + public LineNumberTable(LineNumberTable lineNumberTable) { + this( + lineNumberTable.getName_index(), + lineNumberTable.getLength(), + lineNumberTable.getLineNumberTable(), + lineNumberTable.getConstantPool()); + } + + public LineNumberTable( + int value, int value2, LineNumber[] lineNumbers, ConstantPool constantPool) { + super((byte) 4, value, value2, constantPool); + this.setLineNumberTable(lineNumbers); + } + + @Override + public Attribute copy(ConstantPool constantPool) { + LineNumberTable lineNumberTable; + (lineNumberTable = (LineNumberTable) this.clone()).line_number_table = + new LineNumber[this.line_number_table_length]; + int value; + for (int value2 = value = 0; value2 < this.line_number_table_length; value2 = value) { + LineNumber[] lineNumbers = lineNumberTable.line_number_table; + LineNumber lineNumber = this.line_number_table[value].copy(); + int value3 = value; + value++; + lineNumbers[value3] = lineNumber; + } + lineNumberTable.constant_pool = constantPool; + return lineNumberTable; + } + + public final LineNumber[] getLineNumberTable() { + return this.line_number_table; + } + + public final void setLineNumberTable(LineNumber[] lineNumbers) { + this.line_number_table = lineNumbers; + this.line_number_table_length = lineNumbers == null ? 0 : lineNumbers.length; + } + + public LineNumberTable( + int value, int value2, DataInputStream dataInputStream, ConstantPool constantPool) + throws IOException { + this(value, value2, (LineNumber[]) null, constantPool); + this.line_number_table_length = dataInputStream.readUnsignedShort(); + this.line_number_table = new LineNumber[this.line_number_table_length]; + int value3; + for (int value4 = value3 = 0; value4 < this.line_number_table_length; value4 = value3) { + LineNumber[] lineNumbers = this.line_number_table; + LineNumber lineNumber = new LineNumber(dataInputStream); + int value5 = value3; + value3++; + lineNumbers[value5] = lineNumber; + } + } + + public final int getTableLength() { + return this.line_number_table_length; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/LocalVariable.java b/src/main/java/com/allatori/lib/bcel/classfile/LocalVariable.java new file mode 100644 index 0000000..fc3cbd2 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/LocalVariable.java @@ -0,0 +1,137 @@ +package com.allatori.lib.bcel.classfile; + +import com.allatori.lib.bcel.Constants; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.Serializable; + +public final class LocalVariable implements Constants, Cloneable, Node, Serializable { + + public int length; + + public ConstantPool constant_pool; + + public int index; + + public int name_index; + + public int start_pc; + + public int signature_index; + + public final int getSignature_index() { + return this.signature_index; + } + + public final void setLength(int length) { + this.length = length; + } + + public LocalVariable copy() { + try { + return (LocalVariable) this.clone(); + } catch (CloneNotSupportedException cloneNotSupportedException) { + return null; + } + } + + public final int getIndex() { + return this.index; + } + + public final void setSignature_index(int signature_index) { + this.signature_index = signature_index; + } + + public final String getText() { + return ((ConstantUtf8) this.constant_pool.getConstant(this.name_index, (byte) 1)).getBytes(); + } + + public final int getStart_pc() { + return this.start_pc; + } + + public final void setIndex(int index) { + this.index = index; + } + + public final ConstantPool getConstantPool() { + return this.constant_pool; + } + + public final void dump(DataOutputStream dataOutputStream) throws IOException { + dataOutputStream.writeShort(this.start_pc); + dataOutputStream.writeShort(this.length); + dataOutputStream.writeShort(this.name_index); + dataOutputStream.writeShort(this.signature_index); + dataOutputStream.writeShort(this.index); + } + + public LocalVariable(LocalVariable localVariable) { + this( + localVariable.getStart_pc(), + localVariable.getLength(), + localVariable.getName_index(), + localVariable.getSignature_index(), + localVariable.getIndex(), + localVariable.getConstantPool()); + } + + public LocalVariable(DataInputStream dataInputStream, ConstantPool constantPool) + throws IOException { + this( + dataInputStream.readUnsignedShort(), + dataInputStream.readUnsignedShort(), + dataInputStream.readUnsignedShort(), + dataInputStream.readUnsignedShort(), + dataInputStream.readUnsignedShort(), + constantPool); + } + + public final void setStart_pc(int start_pc) { + this.start_pc = start_pc; + } + + public final void setConstantPool(ConstantPool constantPool) { + this.constant_pool = constantPool; + } + + @Override + public void accept(Visitor visitor) { + visitor.visitLocalVariable(this); + } + + public final void setName_index(int name_index) { + this.name_index = name_index; + } + + public LocalVariable( + int start_pc, + int length, + int name_index, + int signature_index, + int index, + ConstantPool constantPool) { + super(); + this.start_pc = start_pc; + this.length = length; + this.name_index = name_index; + this.signature_index = signature_index; + this.index = index; + this.constant_pool = constantPool; + } + + public final int getLength() { + return this.length; + } + + public final int getName_index() { + return this.name_index; + } + + public final String getText2() { + return ((ConstantUtf8) this.constant_pool.getConstant(this.signature_index, (byte) 1)) + .getBytes(); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/LocalVariableTable.java b/src/main/java/com/allatori/lib/bcel/classfile/LocalVariableTable.java new file mode 100644 index 0000000..83e3200 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/LocalVariableTable.java @@ -0,0 +1,119 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public class LocalVariableTable extends Attribute { + + public int local_variable_table_length; + + public LocalVariable[] local_variable_table; + + public LocalVariableTable(LocalVariableTable localVariableTable) { + this( + localVariableTable.getName_index(), + localVariableTable.getLength(), + localVariableTable.getLocalVariableTable(), + localVariableTable.getConstantPool()); + } + + public final LocalVariable getLocalVariable(int value, int value2) { + int value3; + for (int value4 = value3 = 0; value4 < this.local_variable_table_length; value4 = ++value3) { + if (this.local_variable_table[value3].getIndex() == value) { + int value5; + int value6 = + (value5 = this.local_variable_table[value3].getStart_pc()) + + this.local_variable_table[value3].getLength(); + if (value2 >= value5 && value2 < value6) { + return this.local_variable_table[value3]; + } + } + } + return null; + } + + public LocalVariableTable( + int value, int value2, DataInputStream dataInputStream, ConstantPool constantPool) + throws IOException { + this(value, value2, (LocalVariable[]) null, constantPool); + this.local_variable_table_length = dataInputStream.readUnsignedShort(); + this.local_variable_table = new LocalVariable[this.local_variable_table_length]; + int value3; + for (int value4 = value3 = 0; value4 < this.local_variable_table_length; value4 = value3) { + LocalVariable[] localVariables = this.local_variable_table; + LocalVariable localVariable = new LocalVariable(dataInputStream, constantPool); + int value5 = value3; + value3++; + localVariables[value5] = localVariable; + } + } + + /** + * @deprecated + */ + public final LocalVariable getLocalVariable(int value) { + int value2; + for (int value3 = value2 = 0; value3 < this.local_variable_table_length; value3 = ++value2) { + if (this.local_variable_table[value2].getIndex() == value) { + return this.local_variable_table[value2]; + } + } + return null; + } + + @Override + public Attribute copy(ConstantPool constantPool) { + LocalVariableTable localVariableTable; + (localVariableTable = (LocalVariableTable) this.clone()).local_variable_table = + new LocalVariable[this.local_variable_table_length]; + int value; + for (int value2 = value = 0; value2 < this.local_variable_table_length; value2 = value) { + LocalVariable[] localVariables = localVariableTable.local_variable_table; + LocalVariable localVariable = this.local_variable_table[value].copy(); + int value3 = value; + value++; + localVariables[value3] = localVariable; + } + localVariableTable.constant_pool = constantPool; + return localVariableTable; + } + + public final void setLocalVariableTable(LocalVariable[] localVariables) { + this.local_variable_table = localVariables; + this.local_variable_table_length = localVariables == null ? 0 : localVariables.length; + } + + @Override + public final void dump(DataOutputStream dataOutputStream) throws IOException { + int value = 0; + super.dump(dataOutputStream); + dataOutputStream.writeShort(this.local_variable_table_length); + for (int index = 0; value < this.local_variable_table_length; value = index) { + int value2 = index; + LocalVariable[] localVariables = this.local_variable_table; + index++; + localVariables[value2].dump(dataOutputStream); + } + } + + public final int getTableLength() { + return this.local_variable_table_length; + } + + public final LocalVariable[] getLocalVariableTable() { + return this.local_variable_table; + } + + @Override + public void accept(Visitor visitor) { + visitor.visitLocalVariableTable(this); + } + + public LocalVariableTable( + int value, int value2, LocalVariable[] localVariables, ConstantPool constantPool) { + super((byte) 5, value, value2, constantPool); + this.setLocalVariableTable(localVariables); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/LocalVariableTypeTable.java b/src/main/java/com/allatori/lib/bcel/classfile/LocalVariableTypeTable.java new file mode 100644 index 0000000..2d4853b --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/LocalVariableTypeTable.java @@ -0,0 +1,100 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public class LocalVariableTypeTable extends Attribute { + + public LocalVariable[] local_variable_type_table; + + public int count; + + public LocalVariableTypeTable(LocalVariableTypeTable localVariableTypeTable) { + this( + localVariableTypeTable.getName_index(), + localVariableTypeTable.getLength(), + localVariableTypeTable.getLocalVariableTypeTable(), + localVariableTypeTable.getConstantPool()); + } + + public LocalVariableTypeTable( + int value, int value2, LocalVariable[] localVariables, ConstantPool constantPool) { + super((byte) 17, value, value2, constantPool); + this.setLocalVariableTable(localVariables); + } + + public final LocalVariable getLocalVariable(int value) { + int value2; + for (int value3 = value2 = 0; value3 < this.count; value3 = ++value2) { + if (this.local_variable_type_table[value2].getIndex() == value) { + return this.local_variable_type_table[value2]; + } + } + return null; + } + + public final LocalVariable[] getLocalVariableTypeTable() { + return this.local_variable_type_table; + } + + @Override + public void accept(Visitor visitor) { + visitor.visitLocalVariableTypeTable(this); + } + + public final void setLocalVariableTable(LocalVariable[] localVariables) { + this.local_variable_type_table = localVariables; + this.count = localVariables == null ? 0 : localVariables.length; + } + + @Override + public Attribute copy(ConstantPool constantPool) { + LocalVariableTypeTable localVariableTypeTable; + (localVariableTypeTable = (LocalVariableTypeTable) this.clone()).local_variable_type_table = + new LocalVariable[this.count]; + int value; + for (int value2 = value = 0; value2 < this.count; value2 = value) { + LocalVariable[] localVariables = localVariableTypeTable.local_variable_type_table; + LocalVariable localVariable = this.local_variable_type_table[value].copy(); + int value3 = value; + value++; + localVariables[value3] = localVariable; + } + localVariableTypeTable.constant_pool = constantPool; + return localVariableTypeTable; + } + + public LocalVariableTypeTable( + int value, int value2, DataInputStream dataInputStream, ConstantPool constantPool) + throws IOException { + this(value, value2, (LocalVariable[]) null, constantPool); + this.count = dataInputStream.readUnsignedShort(); + this.local_variable_type_table = new LocalVariable[this.count]; + int value3; + for (int value4 = value3 = 0; value4 < this.count; value4 = value3) { + LocalVariable[] localVariables = this.local_variable_type_table; + LocalVariable localVariable = new LocalVariable(dataInputStream, constantPool); + int value5 = value3; + value3++; + localVariables[value5] = localVariable; + } + } + + public final int getTableLength() { + return this.count; + } + + @Override + public final void dump(DataOutputStream dataOutputStream) throws IOException { + int value = 0; + super.dump(dataOutputStream); + dataOutputStream.writeShort(this.count); + for (int index = 0; value < this.count; value = index) { + int value2 = index; + LocalVariable[] localVariables = this.local_variable_type_table; + index++; + localVariables[value2].dump(dataOutputStream); + } + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/Method.java b/src/main/java/com/allatori/lib/bcel/classfile/Method.java new file mode 100644 index 0000000..143972c --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/Method.java @@ -0,0 +1,93 @@ +package com.allatori.lib.bcel.classfile; + +import com.allatori.lib.bcel.generic.Type; +import com.allatori.lib.bcel.util.BCELComparator; +import com.allatori.lib.bcel.util.comparator.MethodComparator2; +import java.io.DataInputStream; +import java.io.IOException; + +public final class Method extends FieldOrMethod { + + public static BCELComparator _cmp = new MethodComparator2(); + + public static BCELComparator getComparator() { + return _cmp; + } + + public final LineNumberTable getLineNumberTable() { + Code code; + return (code = this.getCode()) == null ? null : code.getLineNumberTable(); + } + + public static void setComparator(BCELComparator bCELComparator) { + _cmp = bCELComparator; + } + + public Type getReturnType() { + return Type.getReturnType(this.getText2()); + } + + public final ExceptionTable getExceptionTable() { + int value; + for (int value2 = value = 0; value2 < this.count2; value2 = ++value) { + if (this.attributes[value] instanceof ExceptionTable) { + return (ExceptionTable) this.attributes[value]; + } + } + return null; + } + + public final Method copy(ConstantPool constantPool) { + return (Method) this.copy_(constantPool); + } + + public final Code getCode() { + int value; + for (int value2 = value = 0; value2 < this.count2; value2 = ++value) { + if (this.attributes[value] instanceof Code) { + return (Code) this.attributes[value]; + } + } + return null; + } + + public Type[] getArgumentTypes() { + return Type.getArgumentTypes(this.getText2()); + } + + public Method( + int value, int value2, int value3, Attribute[] attributes, ConstantPool constantPool) { + super(value, value2, value3, attributes, constantPool); + } + + @Override + public boolean equals(Object result) { + return _cmp.equals(this, result); + } + + public Method(Method method) { + super(method); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitMethod(this); + } + + public Method(DataInputStream dataInputStream, ConstantPool constantPool) + throws IOException, ClassFormatException { + super(dataInputStream, constantPool); + } + + public final LocalVariableTable getLocalVariableTable() { + Code code; + return (code = this.getCode()) == null ? null : code.getLocalVariableTable(); + } + + @Override + public int hashCode() { + return _cmp.hashCode(this); + } + + public Method() {} +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/MethodParameter.java b/src/main/java/com/allatori/lib/bcel/classfile/MethodParameter.java new file mode 100644 index 0000000..3f08abc --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/MethodParameter.java @@ -0,0 +1,68 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInput; +import java.io.DataOutputStream; +import java.io.IOException; + +public class MethodParameter implements Cloneable, Node { + + public int nameIndex; + + public int accessFlags; + + public MethodParameter() {} + + public boolean isEnabled() { + return (this.accessFlags & 16) != 0; + } + + public MethodParameter(DataInput dataInput) throws IOException { + super(); + this.nameIndex = dataInput.readUnsignedShort(); + this.accessFlags = dataInput.readUnsignedShort(); + } + + public int getNameIndex() { + return this.nameIndex; + } + + public MethodParameter copy() { + try { + return (MethodParameter) this.clone(); + } catch (CloneNotSupportedException cloneNotSupportedException) { + return null; + } + } + + public boolean isEnabled2() { + return (this.accessFlags & -32768) != 0; + } + + @Override + public void accept(Visitor visitor) {} + + public void setNameIndex(int nameIndex) { + this.nameIndex = nameIndex; + } + + public int getAccessFlags() { + return this.accessFlags; + } + + public String getParameterName(ConstantPool constantPool) { + return this.nameIndex == 0 ? null : constantPool.createText(this.nameIndex, (byte) 1); + } + + public boolean isEnabled3() { + return (this.accessFlags & 4096) != 0; + } + + public final void dump(DataOutputStream dataOutputStream) throws IOException { + dataOutputStream.writeShort(this.nameIndex); + dataOutputStream.writeShort(this.accessFlags); + } + + public void setAccessFlags(int accessFlags) { + this.accessFlags = accessFlags; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/MethodParameters.java b/src/main/java/com/allatori/lib/bcel/classfile/MethodParameters.java new file mode 100644 index 0000000..6ad55ec --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/MethodParameters.java @@ -0,0 +1,70 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInput; +import java.io.DataOutputStream; +import java.io.IOException; + +public class MethodParameters extends Attribute { + + public MethodParameter[] parameters; + + public static final MethodParameter[] METHOD_PARAMETERS = new MethodParameter[0]; + + @Override + public void dump(DataOutputStream dataOutputStream) throws IOException { + super.dump(dataOutputStream); + dataOutputStream.writeByte(this.parameters.length); + MethodParameter[] methodParameters = this.parameters; + int value = this.parameters.length; + int value2; + for (int value3 = value2 = 0; value3 < value; value3 = value2) { + int value4 = value2; + value2++; + methodParameters[value4].dump(dataOutputStream); + } + } + + public MethodParameter[] getParameters() { + return this.parameters; + } + + public void setParameters(MethodParameter[] methodParameters) { + this.parameters = methodParameters != null ? methodParameters : METHOD_PARAMETERS; + } + + @Override + public void accept(Visitor visitor) {} + + @Override + public Attribute copy(ConstantPool constantPool) { + MethodParameters methodParameters; + (methodParameters = (MethodParameters) this.clone()).parameters = + new MethodParameter[this.parameters.length]; + int value; + for (int value2 = value = 0; value2 < this.parameters.length; value2 = value) { + MethodParameter[] methodParameters2 = methodParameters.parameters; + MethodParameter methodParameter = this.parameters[value].copy(); + int value3 = value; + value++; + methodParameters2[value3] = methodParameter; + } + methodParameters.setConstantPool(constantPool); + return methodParameters; + } + + public MethodParameters(int value, int value2, DataInput dataInput, ConstantPool constantPool) + throws IOException { + super((byte) 21, value, value2, constantPool); + this.parameters = METHOD_PARAMETERS; + int value3; + this.parameters = new MethodParameter[value3 = dataInput.readUnsignedByte()]; + int value4; + for (int value5 = value4 = 0; value5 < value3; value5 = value4) { + MethodParameter[] methodParameters = this.parameters; + MethodParameter methodParameter = new MethodParameter(dataInput); + int value6 = value4; + value4++; + methodParameters[value6] = methodParameter; + } + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/NestHost.java b/src/main/java/com/allatori/lib/bcel/classfile/NestHost.java new file mode 100644 index 0000000..8370153 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/NestHost.java @@ -0,0 +1,54 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public final class NestHost extends Attribute { + + public int hostClassIndex; + + @Override + public final void dump(DataOutputStream dataOutputStream) throws IOException { + super.dump(dataOutputStream); + dataOutputStream.writeShort(this.hostClassIndex); + } + + public final void setHostClassIndex(int hostClassIndex) { + this.hostClassIndex = hostClassIndex; + } + + public final int getHostClassIndex() { + return this.hostClassIndex; + } + + @Override + public Attribute copy(ConstantPool constantPool) { + return (NestHost) this.clone(); + } + + public final ConstantClass getConstantClass() { + return (ConstantClass) this.constant_pool.getConstant(this.hostClassIndex, (byte) 7); + } + + public NestHost(int value, int value2, int hostClassIndex, ConstantPool constantPool) { + super((byte) 22, value, value2, constantPool); + this.hostClassIndex = hostClassIndex; + } + + @Override + public void accept(Visitor visitor) {} + + public NestHost(int value, int value2, DataInputStream dataInputStream, ConstantPool constantPool) + throws IOException { + this(value, value2, dataInputStream.readUnsignedShort(), constantPool); + } + + public NestHost(NestHost nestHost) { + this( + nestHost.getName_index(), + nestHost.getLength(), + nestHost.getHostClassIndex(), + nestHost.getConstantPool()); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/NestMembers.java b/src/main/java/com/allatori/lib/bcel/classfile/NestMembers.java new file mode 100644 index 0000000..96f7cdc --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/NestMembers.java @@ -0,0 +1,81 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public final class NestMembers extends Attribute { + + public int classes; + + public int[] classes2; + + @Override + public void accept(Visitor visitor) {} + + public NestMembers( + int value, int value2, DataInputStream dataInputStream, ConstantPool constantPool) + throws IOException { + this(value, value2, (int[]) null, constantPool); + int value3 = 0; + this.classes = dataInputStream.readUnsignedShort(); + this.classes2 = new int[this.classes]; + for (int index = 0; value3 < this.classes; value3 = index) { + int[] values = this.classes2; + int value4 = dataInputStream.readUnsignedShort(); + int value5 = index; + index++; + values[value5] = value4; + } + } + + public final void setClasses(int[] classes2) { + this.classes2 = classes2; + this.classes = classes2 == null ? 0 : classes2.length; + } + + public final int getNumberClasses() { + return this.classes; + } + + @Override + public final void dump(DataOutputStream dataOutputStream) throws IOException { + int value = 0; + super.dump(dataOutputStream); + dataOutputStream.writeShort(this.classes); + for (int index = 0; value < this.classes; value = index) { + int value2 = index; + int[] values = this.classes2; + index++; + dataOutputStream.writeShort(values[value2]); + } + } + + public NestMembers(int value, int value2, int[] values, ConstantPool constantPool) { + super((byte) 23, value, value2, constantPool); + this.setClasses(this.classes2); + } + + public final int[] getClasses() { + return this.classes2; + } + + @Override + public Attribute copy(ConstantPool constantPool) { + NestMembers nestMembers = (NestMembers) this.clone(); + if (this.classes2 != null) { + nestMembers.classes2 = new int[this.classes2.length]; + System.arraycopy(this.classes2, 0, nestMembers.classes2, 0, this.classes2.length); + } + nestMembers.constant_pool = constantPool; + return nestMembers; + } + + public NestMembers(NestMembers nestMembers) { + this( + nestMembers.getName_index(), + nestMembers.getLength(), + nestMembers.getClasses(), + nestMembers.getConstantPool()); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/Node.java b/src/main/java/com/allatori/lib/bcel/classfile/Node.java new file mode 100644 index 0000000..de3ddb3 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/Node.java @@ -0,0 +1,6 @@ +package com.allatori.lib.bcel.classfile; + +public interface Node { + + void accept(Visitor visitor); +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/PMGClass.java b/src/main/java/com/allatori/lib/bcel/classfile/PMGClass.java new file mode 100644 index 0000000..7c8d642 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/PMGClass.java @@ -0,0 +1,80 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public final class PMGClass extends Attribute { + + public int pmg_class_index; + + public int pmg_index; + + public PMGClass( + int value, int value2, int pmg_index, int pmg_class_index, ConstantPool constantPool) { + super((byte) 9, value, value2, constantPool); + this.pmg_index = pmg_index; + this.pmg_class_index = pmg_class_index; + } + + @Override + public void accept(Visitor visitor) { + System.err.println("Visiting non-standard PMGClass object"); + } + + public final String getText() { + return ((ConstantUtf8) this.constant_pool.getConstant(this.pmg_index, (byte) 1)).getBytes(); + } + + @Override + public final void dump(DataOutputStream dataOutputStream) throws IOException { + super.dump(dataOutputStream); + dataOutputStream.writeShort(this.pmg_index); + dataOutputStream.writeShort(this.pmg_class_index); + } + + public final void setPmg_class_index(int pmg_class_index) { + this.pmg_class_index = pmg_class_index; + } + + public final int getPmg_class_index() { + return this.pmg_class_index; + } + + public final String getText2() { + return ((ConstantUtf8) this.constant_pool.getConstant(this.pmg_class_index, (byte) 1)) + .getBytes(); + } + + public PMGClass(int value, int value2, DataInputStream dataInputStream, ConstantPool constantPool) + throws IOException { + this( + value, + value2, + dataInputStream.readUnsignedShort(), + dataInputStream.readUnsignedShort(), + constantPool); + } + + public PMGClass(PMGClass pMGClass) { + this( + pMGClass.getName_index(), + pMGClass.getLength(), + pMGClass.getPmg_index(), + pMGClass.getPmg_class_index(), + pMGClass.getConstantPool()); + } + + public final int getPmg_index() { + return this.pmg_index; + } + + @Override + public Attribute copy(ConstantPool constantPool) { + return (PMGClass) this.clone(); + } + + public final void setPmg_index(int pmg_index) { + this.pmg_index = pmg_index; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/ParameterAnnotationEntry.java b/src/main/java/com/allatori/lib/bcel/classfile/ParameterAnnotationEntry.java new file mode 100644 index 0000000..b63255f --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/ParameterAnnotationEntry.java @@ -0,0 +1,39 @@ +package com.allatori.lib.bcel.classfile; + +import com.allatori.lib.bcel.Constants; +import java.io.DataInputStream; +import java.io.IOException; + +public class ParameterAnnotationEntry implements Node, Constants { + + public int count; + + public AnnotationEntry[] annotation_table; + + public AnnotationEntry[] getAnnotationEntries() { + return this.annotation_table; + } + + public final int getCount() { + return this.count; + } + + @Override + public void accept(Visitor visitor) {} + + public ParameterAnnotationEntry( + DataInputStream dataInputStream, ConstantPool constantPool, boolean matches) + throws IOException { + this.count = dataInputStream.readUnsignedShort(); + this.annotation_table = new AnnotationEntry[this.count]; + int value; + for (int value2 = value = 0; value2 < this.count; value2 = value) { + AnnotationEntry[] annotationEntrys = this.annotation_table; + AnnotationEntry annotationEntry = + AnnotationEntry.createAnnotationEntry(dataInputStream, constantPool, matches); + int value3 = value; + value++; + annotationEntrys[value3] = annotationEntry; + } + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/ParameterAnnotations.java b/src/main/java/com/allatori/lib/bcel/classfile/ParameterAnnotations.java new file mode 100644 index 0000000..7c4f124 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/ParameterAnnotations.java @@ -0,0 +1,91 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public abstract class ParameterAnnotations extends Attribute { + + public ParameterAnnotationEntry[] parameter_annotation_table; + + public int count; + + public ParameterAnnotations( + byte value, + int value2, + int value3, + DataInputStream dataInputStream, + ConstantPool constantPool, + boolean matches) + throws IOException { + this(value, value2, value3, (ParameterAnnotationEntry[]) null, constantPool); + this.count = dataInputStream.readUnsignedByte(); + this.parameter_annotation_table = new ParameterAnnotationEntry[this.count]; + int value4; + for (int value5 = value4 = 0; value5 < this.count; value5 = value4) { + ParameterAnnotationEntry[] parameterAnnotationEntrys = this.parameter_annotation_table; + ParameterAnnotationEntry parameterAnnotationEntry = + new ParameterAnnotationEntry(dataInputStream, constantPool, matches); + int value6 = value4; + value4++; + parameterAnnotationEntrys[value6] = parameterAnnotationEntry; + } + } + + @Override + public void accept(Visitor visitor) {} + + public final int getCount() { + return this.count; + } + + @Override + public final void dump(DataOutputStream dataOutputStream) throws IOException { + super.dump(dataOutputStream); + this.dump2(dataOutputStream); + } + + public ParameterAnnotationEntry[] getParameter_annotation_table() { + return this.parameter_annotation_table; + } + + public ParameterAnnotations( + byte value, + int value2, + int value3, + ParameterAnnotationEntry[] parameterAnnotationEntrys, + ConstantPool constantPool) { + super(value, value2, value3, constantPool); + this.setParameterAnnotationTable(parameterAnnotationEntrys); + } + + public void dump2(DataOutputStream dataOutputStream) throws IOException { + if (this.parameter_annotation_table != null) { + dataOutputStream.writeByte(this.parameter_annotation_table.length); + int value; + for (int value2 = value = 0; + value2 < this.parameter_annotation_table.length; + value2 = ++value) { + AnnotationEntry[] annotationEntries = + this.parameter_annotation_table[value].getAnnotationEntries(); + dataOutputStream.writeShort(annotationEntries.length); + int value3; + for (int value4 = value3 = 0; value4 < annotationEntries.length; value4 = value3) { + int value5 = value3; + value3++; + annotationEntries[value5].dump(dataOutputStream); + } + } + } + } + + public final void setParameterAnnotationTable( + ParameterAnnotationEntry[] parameterAnnotationEntrys) { + this.parameter_annotation_table = parameterAnnotationEntrys; + this.count = parameterAnnotationEntrys == null ? 0 : parameterAnnotationEntrys.length; + } + + public final ParameterAnnotationEntry[] getParameter_annotation_table2() { + return this.parameter_annotation_table; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/RuntimeInvisibleAnnotations.java b/src/main/java/com/allatori/lib/bcel/classfile/RuntimeInvisibleAnnotations.java new file mode 100644 index 0000000..475c8fb --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/RuntimeInvisibleAnnotations.java @@ -0,0 +1,25 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public class RuntimeInvisibleAnnotations extends Annotations { + + @Override + public final void dump(DataOutputStream dataOutputStream) throws IOException { + super.dump(dataOutputStream); + this.writeAnnotations(dataOutputStream); + } + + @Override + public Attribute copy(ConstantPool constantPool) { + return (Annotations) this.clone(); + } + + public RuntimeInvisibleAnnotations( + int value, int value2, DataInputStream dataInputStream, ConstantPool constantPool) + throws IOException { + super((byte) 13, value, value2, dataInputStream, constantPool, false); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/RuntimeInvisibleParameterAnnotations.java b/src/main/java/com/allatori/lib/bcel/classfile/RuntimeInvisibleParameterAnnotations.java new file mode 100644 index 0000000..db897da --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/RuntimeInvisibleParameterAnnotations.java @@ -0,0 +1,18 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInputStream; +import java.io.IOException; + +public class RuntimeInvisibleParameterAnnotations extends ParameterAnnotations { + + public RuntimeInvisibleParameterAnnotations( + int value, int value2, DataInputStream dataInputStream, ConstantPool constantPool) + throws IOException { + super((byte) 15, value, value2, dataInputStream, constantPool, false); + } + + @Override + public Attribute copy(ConstantPool constantPool) { + return (Annotations) this.clone(); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/RuntimeVisibleAnnotations.java b/src/main/java/com/allatori/lib/bcel/classfile/RuntimeVisibleAnnotations.java new file mode 100644 index 0000000..caf7846 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/RuntimeVisibleAnnotations.java @@ -0,0 +1,25 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public class RuntimeVisibleAnnotations extends Annotations { + + @Override + public Attribute copy(ConstantPool constantPool) { + return (Annotations) this.clone(); + } + + @Override + public final void dump(DataOutputStream dataOutputStream) throws IOException { + super.dump(dataOutputStream); + this.writeAnnotations(dataOutputStream); + } + + public RuntimeVisibleAnnotations( + int value, int value2, DataInputStream dataInputStream, ConstantPool constantPool) + throws IOException { + super((byte) 12, value, value2, dataInputStream, constantPool, true); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/RuntimeVisibleParameterAnnotations.java b/src/main/java/com/allatori/lib/bcel/classfile/RuntimeVisibleParameterAnnotations.java new file mode 100644 index 0000000..e11759a --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/RuntimeVisibleParameterAnnotations.java @@ -0,0 +1,18 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInputStream; +import java.io.IOException; + +public class RuntimeVisibleParameterAnnotations extends ParameterAnnotations { + + @Override + public Attribute copy(ConstantPool constantPool) { + return (Annotations) this.clone(); + } + + public RuntimeVisibleParameterAnnotations( + int value, int value2, DataInputStream dataInputStream, ConstantPool constantPool) + throws IOException { + super((byte) 14, value, value2, dataInputStream, constantPool, true); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/Signature$MyByteArrayInputStream.java b/src/main/java/com/allatori/lib/bcel/classfile/Signature$MyByteArrayInputStream.java new file mode 100644 index 0000000..3025976 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/Signature$MyByteArrayInputStream.java @@ -0,0 +1,28 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.ByteArrayInputStream; + +public final class Signature$MyByteArrayInputStream extends ByteArrayInputStream { + + public final int mark() { + return this.pos; + } + + public final void reset(int pos) { + this.pos = pos; + } + + public Signature$MyByteArrayInputStream(String text) { + super(text.getBytes()); + } + + public final String getData() { + return new String(this.buf); + } + + public final void unread() { + if (this.pos > 0) { + this.pos--; + } + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/Signature.java b/src/main/java/com/allatori/lib/bcel/classfile/Signature.java new file mode 100644 index 0000000..df87b86 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/Signature.java @@ -0,0 +1,168 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public final class Signature extends Attribute { + + public int signature_index; + + public final String getText() { + return ((ConstantUtf8) this.constant_pool.getConstant(this.signature_index, (byte) 1)) + .getBytes(); + } + + public static final boolean isFormalParameterList(String text) { + return text.startsWith("<") && text.indexOf(58) > 0; + } + + public Signature( + int value, int value2, DataInputStream dataInputStream, ConstantPool constantPool) + throws IOException { + this(value, value2, dataInputStream.readUnsignedShort(), constantPool); + } + + public Signature(Signature signature) { + this( + signature.getName_index(), + signature.getLength(), + signature.getSignatureIndex(), + signature.getConstantPool()); + } + + public static boolean identStart(int value) { + return value == 84 || value == 76; + } + + public static String translate(String text) { + StringBuffer stringBuffer = new StringBuffer(); + processStringBuffer2(new Signature$MyByteArrayInputStream(text), stringBuffer); + return stringBuffer.toString(); + } + + public static final boolean isActualParameterList(String text) { + return text.startsWith("L") && text.endsWith(">;"); + } + + public final int getSignatureIndex() { + return this.signature_index; + } + + @Override + public final void dump(DataOutputStream dataOutputStream) throws IOException { + super.dump(dataOutputStream); + dataOutputStream.writeShort(this.signature_index); + } + + @Override + public Attribute copy(ConstantPool constantPool) { + return (Signature) this.clone(); + } + + public Signature(int value, int value2, int signature_index, ConstantPool constantPool) { + super((byte) 10, value, value2, constantPool); + this.signature_index = signature_index; + } + + public static final void processStringBuffer( + Signature$MyByteArrayInputStream signature$MyByteArrayInputStream, + StringBuffer stringBuffer) { + int value; + if ((value = signature$MyByteArrayInputStream.read()) == -1) { + throw new RuntimeException( + ("Illegal signature: " + + signature$MyByteArrayInputStream.getData() + + " no ident, reaching EOF")); + } + if (!identStart(value)) { + StringBuffer stringBuffer2 = new StringBuffer(); + int value2 = 1; + for (int value3 = value; Character.isJavaIdentifierPart((char) value3); value3 = value) { + value2++; + stringBuffer2.append((char) value); + value = signature$MyByteArrayInputStream.read(); + } + if (value == 58) { + "Ljava/lang/Object".length(); + signature$MyByteArrayInputStream.skip(17L); + stringBuffer.append(stringBuffer2); + signature$MyByteArrayInputStream.read(); + signature$MyByteArrayInputStream.unread(); + } else { + int value4; + for (int value5 = value4 = 0; value5 < value2; value5 = value4) { + value4++; + signature$MyByteArrayInputStream.unread(); + } + } + } else { + StringBuffer stringBuffer3 = new StringBuffer(); + int value6 = signature$MyByteArrayInputStream.read(); + do { + stringBuffer3.append((char) value6); + value6 = signature$MyByteArrayInputStream.read(); + } while (value6 != -1 && (Character.isJavaIdentifierPart((char) value6) || value6 == 47)); + stringBuffer.append(stringBuffer3.toString().replace('/', '.')); + if (value6 != -1) { + signature$MyByteArrayInputStream.unread(); + } + } + } + + public static final void processStringBuffer2( + Signature$MyByteArrayInputStream signature$MyByteArrayInputStream, + StringBuffer stringBuffer) { + processStringBuffer(signature$MyByteArrayInputStream, stringBuffer); + int value; + Signature$MyByteArrayInputStream signature$MyByteArrayInputStream2; + if ((value = signature$MyByteArrayInputStream.read()) != 60 && value != 40) { + signature$MyByteArrayInputStream2 = signature$MyByteArrayInputStream; + signature$MyByteArrayInputStream.unread(); + } else { + stringBuffer.append((char) value); + processStringBuffer2(signature$MyByteArrayInputStream, stringBuffer); + int value2; + for (Signature$MyByteArrayInputStream signature$MyByteArrayInputStream3 = + signature$MyByteArrayInputStream; + (value2 = signature$MyByteArrayInputStream3.read()) != 62 && value2 != 41; + signature$MyByteArrayInputStream3 = signature$MyByteArrayInputStream) { + if (value2 == -1) { + throw new RuntimeException( + ("Illegal signature: " + + signature$MyByteArrayInputStream.getData() + + " reaching EOF")); + } + stringBuffer.append(", "); + signature$MyByteArrayInputStream.unread(); + processStringBuffer2(signature$MyByteArrayInputStream, stringBuffer); + } + stringBuffer.append((char) value2); + signature$MyByteArrayInputStream2 = signature$MyByteArrayInputStream; + } + int value3; + if (identStart(value3 = signature$MyByteArrayInputStream2.read())) { + signature$MyByteArrayInputStream.unread(); + processStringBuffer2(signature$MyByteArrayInputStream, stringBuffer); + } else if (value3 == 41) { + signature$MyByteArrayInputStream.unread(); + } else { + if (value3 != 59) { + throw new RuntimeException( + ("Illegal signature: " + + signature$MyByteArrayInputStream.getData() + + " read " + + ((char) value3))); + } + } + } + + @Override + public void accept(Visitor visitor) { + visitor.visitSignature(this); + } + + public final void setSignatureIndex(int signature_index) { + this.signature_index = signature_index; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/SimpleElementValue.java b/src/main/java/com/allatori/lib/bcel/classfile/SimpleElementValue.java new file mode 100644 index 0000000..6263af1 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/SimpleElementValue.java @@ -0,0 +1,159 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataOutputStream; +import java.io.IOException; + +public class SimpleElementValue extends ElementValue { + + public int index; + + public short getValueShort() { + if (this.type != 83) { + throw new RuntimeException("Dont call getValueShort() on a non SHORT ElementValue"); + } else { + return (short) ((ConstantInteger) this.cpool.getConstant(this.getIndex())).getBytes(); + } + } + + public SimpleElementValue(int value, int index, ConstantPool constantPool) { + super(value, constantPool); + this.index = index; + } + + public int calculateCount() { + if (this.type != 73) { + throw new RuntimeException("Dont call getValueString() on a non STRING ElementValue"); + } else { + return ((ConstantInteger) this.cpool.getConstant(this.getIndex(), (byte) 3)).getBytes(); + } + } + + public float getValueFloat() { + if (this.type != 70) { + throw new RuntimeException("Dont call getValueFloat() on a non FLOAT ElementValue"); + } else { + return ((ConstantFloat) this.cpool.getConstant(this.getIndex())).getBytes(); + } + } + + public boolean getValueBoolean() { + if (this.type != 90) { + throw new RuntimeException("Dont call getValueBoolean() on a non BOOLEAN ElementValue"); + } else { + return ((ConstantInteger) this.cpool.getConstant(this.getIndex())).getBytes() != 0; + } + } + + public int getIndex() { + return this.index; + } + + public double getValueDouble() { + if (this.type != 68) { + throw new RuntimeException("Dont call getValueDouble() on a non DOUBLE ElementValue"); + } else { + return ((ConstantDouble) this.cpool.getConstant(this.getIndex())).getBytes(); + } + } + + public void setIndex(int index) { + this.index = index; + } + + public long getValueLong() { + if (this.type != 74) { + throw new RuntimeException("Dont call getValueLong() on a non LONG ElementValue"); + } else { + return ((ConstantLong) this.cpool.getConstant(this.getIndex())).getBytes(); + } + } + + @Override + public void dump(DataOutputStream dataOutputStream) throws IOException { + dataOutputStream.writeByte(this.type); + switch (this.type) { + case 66: + case 67: + case 68: + case 70: + case 73: + case 74: + case 83: + case 90: + case 115: + dataOutputStream.writeShort(this.getIndex()); + return; + default: + throw new RuntimeException( + ("SimpleElementValue doesnt know how to write out type " + this.type)); + } + } + + public String createText2() { + if (this.type != 115) { + throw new RuntimeException("Dont call getValueString() on a non STRING ElementValue"); + } else { + return ((ConstantUtf8) this.cpool.getConstant(this.getIndex(), (byte) 1)).getBytes(); + } + } + + public char getValueChar() { + if (this.type != 67) { + throw new RuntimeException("Dont call getValueChar() on a non CHAR ElementValue"); + } else { + return (char) + ((ConstantInteger) this.cpool.getConstant(this.getIndex(), (byte) 3)).getBytes(); + } + } + + @Override + public String getText() { + switch (this.type) { + case 66: + return Integer.toString( + ((ConstantInteger) this.cpool.getConstant(this.getIndex(), (byte) 3)).getBytes()); + case 67: + return String.valueOf( + (char) + ((ConstantInteger) this.cpool.getConstant(this.getIndex(), (byte) 3)).getBytes()); + case 68: + return Double.toString( + ((ConstantDouble) this.cpool.getConstant(this.getIndex(), (byte) 6)).getBytes()); + case 70: + return Float.toString( + ((ConstantFloat) this.cpool.getConstant(this.getIndex(), (byte) 4)).getBytes()); + case 73: + return Integer.toString( + ((ConstantInteger) this.cpool.getConstant(this.getIndex(), (byte) 3)).getBytes()); + case 74: + return Long.toString( + ((ConstantLong) this.cpool.getConstant(this.getIndex(), (byte) 5)).getBytes()); + case 83: + return Integer.toString( + ((ConstantInteger) this.cpool.getConstant(this.getIndex(), (byte) 3)).getBytes()); + case 90: + ConstantInteger constantInteger; + if ((constantInteger = (ConstantInteger) this.cpool.getConstant(this.getIndex(), (byte) 3)) + .getBytes() + == 0) { + return "false"; + } else if (constantInteger.getBytes() != 0) { + return "true"; + } + case 115: + return ((ConstantUtf8) this.cpool.getConstant(this.getIndex(), (byte) 1)).getBytes(); + default: + throw new RuntimeException( + ("SimpleElementValue class does not know how to stringify type " + this.type)); + } + } + + public byte getValueByte() { + if (this.type != 66) { + throw new RuntimeException("Dont call getValueByte() on a non BYTE ElementValue"); + } else { + return (byte) + ((ConstantInteger) this.cpool.getConstant(this.getIndex(), (byte) 3)).getBytes(); + } + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/SourceFile.java b/src/main/java/com/allatori/lib/bcel/classfile/SourceFile.java new file mode 100644 index 0000000..6e5f24b --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/SourceFile.java @@ -0,0 +1,58 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public final class SourceFile extends Attribute { + + public int sourcefile_index; + + public SourceFile(int value, int value2, int sourcefile_index, ConstantPool constantPool) { + super((byte) 0, value, value2, constantPool); + this.sourcefile_index = sourcefile_index; + } + + @Override + public Attribute copy(ConstantPool constantPool) { + return (SourceFile) this.clone(); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitSourceFile(this); + } + + public SourceFile(SourceFile sourceFile) { + this( + sourceFile.getName_index(), + sourceFile.getLength(), + sourceFile.getSourceFileIndex(), + sourceFile.getConstantPool()); + } + + @Override + public final void dump(DataOutputStream dataOutputStream) throws IOException { + super.dump(dataOutputStream); + dataOutputStream.writeShort(this.sourcefile_index); + } + + public final String getText() { + return ((ConstantUtf8) this.constant_pool.getConstant(this.sourcefile_index, (byte) 1)) + .getBytes(); + } + + public SourceFile( + int value, int value2, DataInputStream dataInputStream, ConstantPool constantPool) + throws IOException { + this(value, value2, dataInputStream.readUnsignedShort(), constantPool); + } + + public final void setSourceFileIndex(int sourcefile_index) { + this.sourcefile_index = sourcefile_index; + } + + public final int getSourceFileIndex() { + return this.sourcefile_index; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/StackMap.java b/src/main/java/com/allatori/lib/bcel/classfile/StackMap.java new file mode 100644 index 0000000..102a0cd --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/StackMap.java @@ -0,0 +1,80 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public final class StackMap extends Attribute implements Node { + + public int map_length; + + public StackMapEntry[] map; + + public StackMap(int value, int value2, DataInputStream dataInputStream, ConstantPool constantPool) + throws IOException { + this(value, value2, (StackMapEntry[]) null, constantPool); + this.map_length = dataInputStream.readUnsignedShort(); + this.map = new StackMapEntry[this.map_length]; + int value3; + for (int value4 = value3 = 0; value4 < this.map_length; value4 = value3) { + StackMapEntry[] stackMapEntrys = this.map; + StackMapEntry stackMapEntry = new StackMapEntry(dataInputStream, constantPool); + int value5 = value3; + value3++; + stackMapEntrys[value5] = stackMapEntry; + } + } + + public StackMap( + int value, int value2, StackMapEntry[] stackMapEntrys, ConstantPool constantPool) { + super((byte) 11, value, value2, constantPool); + this.setStackMap(stackMapEntrys); + } + + public final StackMapEntry[] getStackMap() { + return this.map; + } + + @Override + public Attribute copy(ConstantPool constantPool) { + StackMap stackMap; + (stackMap = (StackMap) this.clone()).map = new StackMapEntry[this.map_length]; + int value; + for (int value2 = value = 0; value2 < this.map_length; value2 = value) { + StackMapEntry[] stackMapEntrys = stackMap.map; + StackMapEntry stackMapEntry = this.map[value].copy(); + int value3 = value; + value++; + stackMapEntrys[value3] = stackMapEntry; + } + stackMap.constant_pool = constantPool; + return stackMap; + } + + public final int getMapLength() { + return this.map_length; + } + + @Override + public void accept(Visitor visitor) { + visitor.visitStackMap(this); + } + + public final void setStackMap(StackMapEntry[] stackMapEntrys) { + this.map = stackMapEntrys; + this.map_length = stackMapEntrys == null ? 0 : stackMapEntrys.length; + } + + @Override + public final void dump(DataOutputStream dataOutputStream) throws IOException { + int value = 0; + super.dump(dataOutputStream); + dataOutputStream.writeShort(this.map_length); + for (int index = 0; value < this.map_length; value = index) { + int value2 = index; + StackMapEntry[] stackMapEntrys = this.map; + index++; + stackMapEntrys[value2].dump(dataOutputStream); + } + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/StackMapEntry.java b/src/main/java/com/allatori/lib/bcel/classfile/StackMapEntry.java new file mode 100644 index 0000000..9c40983 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/StackMapEntry.java @@ -0,0 +1,140 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public final class StackMapEntry implements Cloneable { + + public int number_of_locals; + + public ConstantPool constant_pool; + + public int byte_code_offset; + + public StackMapType[] types_of_stack_items; + + public StackMapType[] types_of_locals; + + public int number_of_stack_items; + + public StackMapEntry( + int byte_code_offset, + int number_of_locals, + StackMapType[] stackMapTypes, + int number_of_stack_items, + StackMapType[] stackMapTypes2, + ConstantPool constantPool) { + super(); + this.byte_code_offset = byte_code_offset; + this.number_of_locals = number_of_locals; + this.types_of_locals = stackMapTypes; + this.number_of_stack_items = number_of_stack_items; + this.types_of_stack_items = stackMapTypes2; + this.constant_pool = constantPool; + } + + public StackMapEntry(DataInputStream dataInputStream, ConstantPool constantPool) + throws IOException { + this(dataInputStream.readShort(), dataInputStream.readShort(), null, -1, null, constantPool); + this.types_of_locals = new StackMapType[this.number_of_locals]; + int value; + for (int value2 = value = 0; value2 < this.number_of_locals; value2 = value) { + StackMapType[] stackMapTypes = this.types_of_locals; + StackMapType stackMapType = new StackMapType(dataInputStream, constantPool); + int value3 = value; + value++; + stackMapTypes[value3] = stackMapType; + } + this.number_of_stack_items = dataInputStream.readShort(); + this.types_of_stack_items = new StackMapType[this.number_of_stack_items]; + int value4; + for (int value5 = value4 = 0; value5 < this.number_of_stack_items; value5 = value4) { + StackMapType[] stackMapTypes2 = this.types_of_stack_items; + StackMapType stackMapType2 = new StackMapType(dataInputStream, constantPool); + int value6 = value4; + value4++; + stackMapTypes2[value6] = stackMapType2; + } + } + + public void setByte_code_offset(int byte_code_offset) { + this.byte_code_offset = byte_code_offset; + } + + public void accept(Visitor visitor) { + visitor.visitStackMapEntry(this); + } + + public int getNumber_of_locals() { + return this.number_of_locals; + } + + public int getByte_code_offset() { + return this.byte_code_offset; + } + + public void setNumber_of_stack_items(int number_of_stack_items) { + this.number_of_stack_items = number_of_stack_items; + } + + public final void dump(DataOutputStream dataOutputStream) throws IOException { + int value = 0; + dataOutputStream.writeShort(this.byte_code_offset); + dataOutputStream.writeShort(this.number_of_locals); + for (int index = 0; value < this.number_of_locals; value = index) { + int value2 = index; + StackMapType[] stackMapTypes = this.types_of_locals; + index++; + stackMapTypes[value2].dump(dataOutputStream); + } + dataOutputStream.writeShort(this.number_of_stack_items); + int value3; + for (int value4 = value3 = 0; value4 < this.number_of_stack_items; value4 = value3) { + int value5 = value3; + StackMapType[] stackMapTypes2 = this.types_of_stack_items; + value3++; + stackMapTypes2[value5].dump(dataOutputStream); + } + } + + public int getNumber_of_stack_items() { + return this.number_of_stack_items; + } + + public void setTypes_of_locals(StackMapType[] stackMapTypes) { + this.types_of_locals = stackMapTypes; + } + + public final ConstantPool getConstantPool() { + return this.constant_pool; + } + + public StackMapEntry copy() { + try { + return (StackMapEntry) this.clone(); + } catch (CloneNotSupportedException cloneNotSupportedException) { + return null; + } + } + + public void setTypes_of_stack_items(StackMapType[] stackMapTypes) { + this.types_of_stack_items = stackMapTypes; + } + + public StackMapType[] getTypes_of_locals() { + return this.types_of_locals; + } + + public StackMapType[] getTypes_of_stack_items() { + return this.types_of_stack_items; + } + + public final void setConstantPool(ConstantPool constantPool) { + this.constant_pool = constantPool; + } + + public void setNumber_of_locals(int number_of_locals) { + this.number_of_locals = number_of_locals; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/StackMapTable.java b/src/main/java/com/allatori/lib/bcel/classfile/StackMapTable.java new file mode 100644 index 0000000..5e3b092 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/StackMapTable.java @@ -0,0 +1,80 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public final class StackMapTable extends Attribute { + + public StackMapTableEntry[] stackMapTable; + + public int mapLength; + + public final int getMapLength() { + return this.mapLength; + } + + public StackMapTable( + int value, int value2, StackMapTableEntry[] stackMapTableEntrys, ConstantPool constantPool) { + super((byte) 19, value, value2, constantPool); + this.setStackMap(stackMapTableEntrys); + } + + public final StackMapTableEntry[] getStackMap() { + return this.stackMapTable; + } + + @Override + public final void dump(DataOutputStream dataOutputStream) throws IOException { + int value = 0; + super.dump(dataOutputStream); + dataOutputStream.writeShort(this.mapLength); + for (int index = 0; value < this.mapLength; value = index) { + int value2 = index; + StackMapTableEntry[] stackMapTableEntrys = this.stackMapTable; + index++; + stackMapTableEntrys[value2].dump(dataOutputStream); + } + } + + public final void setStackMap(StackMapTableEntry[] stackMapTableEntrys) { + this.stackMapTable = stackMapTableEntrys; + this.mapLength = stackMapTableEntrys == null ? 0 : stackMapTableEntrys.length; + } + + @Override + public void accept(Visitor visitor) {} + + @Override + public Attribute copy(ConstantPool constantPool) { + StackMapTable stackMapTable2; + (stackMapTable2 = (StackMapTable) this.clone()).stackMapTable = + new StackMapTableEntry[this.mapLength]; + int value; + for (int value2 = value = 0; value2 < this.mapLength; value2 = value) { + StackMapTableEntry[] stackMapTableEntrys = stackMapTable2.stackMapTable; + StackMapTableEntry stackMapTableEntry = this.stackMapTable[value].copy(); + int value3 = value; + value++; + stackMapTableEntrys[value3] = stackMapTableEntry; + } + stackMapTable2.constant_pool = constantPool; + return stackMapTable2; + } + + public StackMapTable( + int value, int value2, DataInputStream dataInputStream, ConstantPool constantPool) + throws IOException { + this(value, value2, (StackMapTableEntry[]) null, constantPool); + this.mapLength = dataInputStream.readUnsignedShort(); + this.stackMapTable = new StackMapTableEntry[this.mapLength]; + int value3; + for (int value4 = value3 = 0; value4 < this.mapLength; value4 = value3) { + StackMapTableEntry[] stackMapTableEntrys = this.stackMapTable; + StackMapTableEntry stackMapTableEntry = new StackMapTableEntry(dataInputStream, constantPool); + int value5 = value3; + value3++; + stackMapTableEntrys[value5] = stackMapTableEntry; + } + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/StackMapTableEntry.java b/src/main/java/com/allatori/lib/bcel/classfile/StackMapTableEntry.java new file mode 100644 index 0000000..4ed98ac --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/StackMapTableEntry.java @@ -0,0 +1,209 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.Serializable; + +public final class StackMapTableEntry implements Cloneable, Serializable { + + public StackMapType[] typesOfStackItems; + + public int numberOfStackItems; + + public int numberOfLocals; + + public final int frameType; + + public StackMapType[] typesOfLocals; + + public int byteCodeOffset; + + public ConstantPool constantPool; + + public void setNumberOfStackItems(int numberOfStackItems) { + this.numberOfStackItems = numberOfStackItems; + } + + public StackMapTableEntry copy() { + try { + return (StackMapTableEntry) this.clone(); + } catch (CloneNotSupportedException cloneNotSupportedException) { + return null; + } + } + + public StackMapTableEntry( + int frameType, + int byteCodeOffset, + int numberOfLocals, + StackMapType[] stackMapTypes, + int numberOfStackItems, + StackMapType[] stackMapTypes2, + ConstantPool constantPool2) { + super(); + this.frameType = frameType; + this.byteCodeOffset = byteCodeOffset; + this.numberOfLocals = numberOfLocals; + this.typesOfLocals = stackMapTypes; + this.numberOfStackItems = numberOfStackItems; + this.typesOfStackItems = stackMapTypes2; + this.constantPool = constantPool2; + } + + public void setNumberOfLocals(int numberOfLocals) { + this.numberOfLocals = numberOfLocals; + } + + public StackMapType[] getTypesOfLocals() { + return this.typesOfLocals; + } + + public int getNumberOfLocals() { + return this.numberOfLocals; + } + + public int getNumberOfStackItems() { + return this.numberOfStackItems; + } + + public void setByteCodeOffset(int byteCodeOffset) { + this.byteCodeOffset = byteCodeOffset; + } + + public void accept(Visitor visitor) {} + + public StackMapTableEntry(DataInputStream dataInputStream, ConstantPool constantPool) + throws IOException { + this(dataInputStream.read(), -1, -1, null, -1, null, constantPool); + if (this.frameType >= 0 && this.frameType <= 63) { + this.byteCodeOffset = this.frameType - 0; + } else if (this.frameType >= 64 && this.frameType <= 127) { + this.byteCodeOffset = this.frameType - 64; + this.numberOfStackItems = 1; + this.typesOfStackItems = new StackMapType[1]; + this.typesOfStackItems[0] = new StackMapType(dataInputStream, constantPool); + } else if (this.frameType == 247) { + this.byteCodeOffset = dataInputStream.readShort(); + this.numberOfStackItems = 1; + this.typesOfStackItems = new StackMapType[1]; + this.typesOfStackItems[0] = new StackMapType(dataInputStream, constantPool); + } else if (this.frameType >= 248 && this.frameType <= 250) { + this.byteCodeOffset = dataInputStream.readShort(); + } else if (this.frameType == 251) { + this.byteCodeOffset = dataInputStream.readShort(); + } else { + if (this.frameType >= 252 && this.frameType <= 254) { + this.byteCodeOffset = dataInputStream.readShort(); + this.numberOfLocals = this.frameType - 251; + this.typesOfLocals = new StackMapType[this.numberOfLocals]; + int value; + for (int value2 = value = 0; value2 < this.numberOfLocals; value2 = value) { + StackMapType[] stackMapTypes = this.typesOfLocals; + StackMapType stackMapType = new StackMapType(dataInputStream, constantPool); + int value3 = value; + value++; + stackMapTypes[value3] = stackMapType; + } + } else { + if (this.frameType != 255) { + throw new ClassFormatException( + ("Invalid frame type found while parsing stack map table: " + this.frameType)); + } + this.byteCodeOffset = dataInputStream.readShort(); + this.numberOfLocals = dataInputStream.readShort(); + this.typesOfLocals = new StackMapType[this.numberOfLocals]; + int value4; + for (int value5 = value4 = 0; value5 < this.numberOfLocals; value5 = value4) { + StackMapType[] stackMapTypes2 = this.typesOfLocals; + StackMapType stackMapType2 = new StackMapType(dataInputStream, constantPool); + int value6 = value4; + value4++; + stackMapTypes2[value6] = stackMapType2; + } + this.numberOfStackItems = dataInputStream.readShort(); + this.typesOfStackItems = new StackMapType[this.numberOfStackItems]; + int value7; + for (int value8 = value7 = 0; value8 < this.numberOfStackItems; value8 = value7) { + StackMapType[] stackMapTypes3 = this.typesOfStackItems; + StackMapType stackMapType3 = new StackMapType(dataInputStream, constantPool); + int value9 = value7; + value7++; + stackMapTypes3[value9] = stackMapType3; + } + } + } + } + + public final void dump(DataOutputStream dataOutputStream) throws IOException { + dataOutputStream.write(this.frameType); + if (this.frameType < 0 || this.frameType > 63) { + if (this.frameType >= 64 && this.frameType <= 127) { + this.typesOfStackItems[0].dump(dataOutputStream); + } else if (this.frameType == 247) { + dataOutputStream.writeShort(this.byteCodeOffset); + this.typesOfStackItems[0].dump(dataOutputStream); + } else if (this.frameType >= 248 && this.frameType <= 250) { + dataOutputStream.writeShort(this.byteCodeOffset); + } else if (this.frameType == 251) { + dataOutputStream.writeShort(this.byteCodeOffset); + } else { + if (this.frameType >= 252 && this.frameType <= 254) { + int value = 0; + dataOutputStream.writeShort(this.byteCodeOffset); + for (int index = 0; value < this.numberOfLocals; value = index) { + int value2 = index; + StackMapType[] stackMapTypes = this.typesOfLocals; + index++; + stackMapTypes[value2].dump(dataOutputStream); + } + } else { + if (this.frameType != 255) { + throw new ClassFormatException(("Invalid Stack map table tag: " + this.frameType)); + } + int value3 = 0; + dataOutputStream.writeShort(this.byteCodeOffset); + dataOutputStream.writeShort(this.numberOfLocals); + for (int index2 = 0; value3 < this.numberOfLocals; value3 = index2) { + int value4 = index2; + StackMapType[] stackMapTypes2 = this.typesOfLocals; + index2++; + stackMapTypes2[value4].dump(dataOutputStream); + } + dataOutputStream.writeShort(this.numberOfStackItems); + int value5; + for (int value6 = value5 = 0; value6 < this.numberOfStackItems; value6 = value5) { + int value7 = value5; + StackMapType[] stackMapTypes3 = this.typesOfStackItems; + value5++; + stackMapTypes3[value7].dump(dataOutputStream); + } + } + } + } + } + + public StackMapType[] getTypesOfStackItems() { + return this.typesOfStackItems; + } + + public final ConstantPool getConstantPool() { + return this.constantPool; + } + + public void setTypesOfStackItems(StackMapType[] stackMapTypes) { + this.typesOfStackItems = stackMapTypes; + } + + public int getByteCodeOffset() { + return this.byteCodeOffset; + } + + public final void setConstantPool(ConstantPool constantPool2) { + this.constantPool = constantPool2; + } + + public void setTypesOfLocals(StackMapType[] stackMapTypes) { + this.typesOfLocals = stackMapTypes; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/StackMapType.java b/src/main/java/com/allatori/lib/bcel/classfile/StackMapType.java new file mode 100644 index 0000000..5c30361 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/StackMapType.java @@ -0,0 +1,88 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public final class StackMapType implements Cloneable { + + public int index; + + public ConstantPool constant_pool; + + public byte type; + + public final ConstantPool getConstantPool() { + return this.constant_pool; + } + + public final void setConstantPool(ConstantPool constantPool) { + this.constant_pool = constantPool; + } + + public byte getType() { + return this.type; + } + + public void setIndex(int index) { + this.index = index; + } + + public StackMapType(DataInputStream dataInputStream, ConstantPool constantPool) + throws IOException { + this(dataInputStream.readByte(), -1, constantPool); + if (this.hasIndex()) { + this.setIndex(dataInputStream.readShort()); + } + this.setConstantPool(constantPool); + } + + public final boolean hasIndex() { + return this.type == 7 || this.type == 8; + } + + public final void dump(DataOutputStream dataOutputStream) throws IOException { + dataOutputStream.writeByte(this.type); + if (this.hasIndex()) { + dataOutputStream.writeShort(this.getIndex()); + } + } + + public StackMapType(byte value, int value2, ConstantPool constantPool) { + super(); + this.index = -1; + this.setType(value); + this.setIndex(value2); + this.setConstantPool(constantPool); + } + + public void setType(byte type) { + if (type >= 0 && type <= 8) { + this.type = type; + } else { + throw new RuntimeException(("Illegal type for StackMapType: " + type)); + } + } + + public int getIndex() { + return this.index; + } + + public String printIndex() { + if (this.type == 7) { + return this.index < 0 + ? ", class=" + : (", class=" + this.constant_pool.getText(this.index, (byte) 7)); + } else { + return this.type == 8 ? (", offset=" + this.index) : ""; + } + } + + public StackMapType copy() { + try { + return (StackMapType) this.clone(); + } catch (CloneNotSupportedException cloneNotSupportedException) { + return null; + } + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/Synthetic.java b/src/main/java/com/allatori/lib/bcel/classfile/Synthetic.java new file mode 100644 index 0000000..883b85f --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/Synthetic.java @@ -0,0 +1,66 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public final class Synthetic extends Attribute { + + public byte[] bytes; + + public Synthetic(int value, int value2, byte[] bytes, ConstantPool constantPool) { + super((byte) 7, value, value2, constantPool); + this.bytes = bytes; + } + + public Synthetic(Synthetic synthetic) { + this( + synthetic.getName_index(), + synthetic.getLength(), + synthetic.getBytes(), + synthetic.getConstantPool()); + } + + @Override + public final void dump(DataOutputStream dataOutputStream) throws IOException { + super.dump(dataOutputStream); + if (this.length > 0) { + dataOutputStream.write(this.bytes, 0, this.length); + } + } + + public final byte[] getBytes() { + return this.bytes; + } + + @Override + public void accept(Visitor visitor) { + visitor.visitSynthetic(this); + } + + @Override + public Attribute copy(ConstantPool constantPool) { + Synthetic synthetic = (Synthetic) this.clone(); + if (this.bytes != null) { + synthetic.bytes = new byte[this.bytes.length]; + System.arraycopy(this.bytes, 0, synthetic.bytes, 0, this.bytes.length); + } + synthetic.constant_pool = constantPool; + return synthetic; + } + + public Synthetic( + int value, int value2, DataInputStream dataInputStream, ConstantPool constantPool) + throws IOException { + this(value, value2, (byte[]) null, constantPool); + if (value2 > 0) { + this.bytes = new byte[value2]; + dataInputStream.readFully(this.bytes); + System.err.println("Synthetic attribute with length > 0"); + } + } + + public final void setBytes(byte[] bytes) { + this.bytes = bytes; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/Unknown.java b/src/main/java/com/allatori/lib/bcel/classfile/Unknown.java new file mode 100644 index 0000000..853090c --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/Unknown.java @@ -0,0 +1,92 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +public final class Unknown extends Attribute { + + public byte[] bytes; + + public static Map unknown_attributes = new HashMap(); + + public String name; + + public Unknown(int value, int value2, byte[] bytes, ConstantPool constantPool) { + super((byte) -1, value, value2, constantPool); + this.bytes = bytes; + this.name = ((ConstantUtf8) constantPool.getConstant(value, (byte) 1)).getBytes(); + unknown_attributes.put(this.name, this); + } + + public Unknown(int value, int value2, DataInputStream dataInputStream, ConstantPool constantPool) + throws IOException { + this(value, value2, (byte[]) null, constantPool); + if (value2 > 0) { + this.bytes = new byte[value2]; + dataInputStream.readFully(this.bytes); + } + } + + @Override + public final String toString() { + return this.name; + } + + public final byte[] getBytes() { + return this.bytes; + } + + public static Unknown[] getUnknownAttributes() { + Unknown[] unknowns = new Unknown[unknown_attributes.size()]; + Iterator iterator2 = unknown_attributes.values().iterator(); + int value = 0; + for (Iterator iterator3 = iterator2; iterator3.hasNext(); iterator3 = iterator2) { + Unknown unknown = (Unknown) iterator2.next(); + int value2 = value; + value++; + unknowns[value2] = unknown; + } + unknown_attributes.clear(); + return unknowns; + } + + public Unknown(Unknown unknown) { + this( + unknown.getName_index(), + unknown.getLength(), + unknown.getBytes(), + unknown.getConstantPool()); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitUnknown(this); + } + + @Override + public final void dump(DataOutputStream dataOutputStream) throws IOException { + super.dump(dataOutputStream); + if (this.length > 0) { + dataOutputStream.write(this.bytes, 0, this.length); + } + } + + public final void setBytes(byte[] bytes) { + this.bytes = bytes; + } + + @Override + public Attribute copy(ConstantPool constantPool) { + Unknown unknown = (Unknown) this.clone(); + if (this.bytes != null) { + unknown.bytes = new byte[this.bytes.length]; + System.arraycopy(this.bytes, 0, unknown.bytes, 0, this.bytes.length); + } + unknown.constant_pool = constantPool; + return unknown; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/Utility$JavaReader.java b/src/main/java/com/allatori/lib/bcel/classfile/Utility$JavaReader.java new file mode 100644 index 0000000..e35c625 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/Utility$JavaReader.java @@ -0,0 +1,46 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.FilterReader; +import java.io.IOException; +import java.io.Reader; + +public class Utility$JavaReader extends FilterReader { + + public Utility$JavaReader(Reader reader) { + super(reader); + } + + @Override + public int read(char[] values, int value, int value2) throws IOException { + int value3; + for (int value4 = value3 = 0; value4 < value2; value4 = value3) { + int value5 = value + value3; + char value6 = (char) this.read(); + value3++; + values[value5] = value6; + } + return value2; + } + + @Override + public int read() throws IOException { + int value; + if ((value = this.in.read()) != 36) { + return value; + } + int value2; + if ((value2 = this.in.read()) < 0) { + return -1; + } + if (value2 >= 48 && value2 <= 57 || value2 >= 97 && value2 <= 102) { + int value3; + if ((value3 = this.in.read()) < 0) { + return -1; + } + char[] values = new char[] {(char) value2, (char) value3}; + return Integer.parseInt(new String(values), 16); + } else { + return Utility.counts[value2]; + } + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/Utility$JavaWriter.java b/src/main/java/com/allatori/lib/bcel/classfile/Utility$JavaWriter.java new file mode 100644 index 0000000..6d4d1f7 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/Utility$JavaWriter.java @@ -0,0 +1,48 @@ +package com.allatori.lib.bcel.classfile; + +import java.io.FilterWriter; +import java.io.IOException; +import java.io.Writer; + +public class Utility$JavaWriter extends FilterWriter { + + @Override + public void write(String text, int value, int value2) throws IOException { + this.write(text.toCharArray(), value, value2); + } + + @Override + public void write(char[] values, int value, int value2) throws IOException { + int value3; + for (int value4 = value3 = 0; value4 < value2; value4 = value3) { + int value5 = value + value3; + value3++; + this.write(values[value5]); + } + } + + @Override + public void write(int value) throws IOException { + if (Utility.isJavaIdentifierPart((char) value) && value != 36) { + this.out.write(value); + } else { + this.out.write(36); + if (value >= 0 && value < 48) { + this.out.write(Utility.counts2[value]); + } else { + char[] values; + if ((values = Integer.toHexString(value).toCharArray()).length == 1) { + this.out.write(48); + this.out.write(values[0]); + } else { + this.out.write(values[0]); + this.out.write(values[1]); + } + } + } + } + + public Utility$JavaWriter(Writer writer) { + super(writer); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/Utility.java b/src/main/java/com/allatori/lib/bcel/classfile/Utility.java new file mode 100644 index 0000000..1ac040c --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/Utility.java @@ -0,0 +1,1265 @@ +package com.allatori.lib.bcel.classfile; + +import com.allatori.lib.bcel.Constants; +import com.allatori.lib.bcel.generic.AnnotationEntryGen; +import com.allatori.lib.bcel.generic.ConstantPoolGen; +import com.allatori.lib.bcel.util.ByteSequence; +import com.allatori.lib.bcel.util.TypeParserThreadLocal2; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.CharArrayReader; +import java.io.CharArrayWriter; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.zip.GZIPInputStream; +import java.util.zip.GZIPOutputStream; + +public abstract class Utility { + + public static ThreadLocal consumed_chars = new TypeParserThreadLocal2(); + + public static boolean wide = false; + + public static int[] counts2 = new int[48]; + + public static int[] counts = new int[256]; + + static { + int value = 0; + int value2; + for (int value3 = value2 = 65; value3 <= 90; value3 = ++value2) { + counts2[value] = value2; + counts[value2] = value++; + } + int value4; + for (int value5 = value4 = 103; value5 <= 122; value5 = ++value4) { + counts2[value] = value4; + counts[value4] = value++; + } + counts2[value] = 36; + counts[36] = value++; + counts2[value] = 95; + counts[95] = value; + } + + public static final int FREE_CHARS = 48; + + public static final char ESCAPE_CHAR = '$'; + + public static final String printArray(Object[] results, boolean matches, boolean matches2) { + if (results == null) { + return null; + } + StringBuffer stringBuffer = new StringBuffer(); + if (matches) { + stringBuffer.append('{'); + } + int value; + for (int value2 = value = 0; value2 < results.length; value2 = ++value) { + if (results[value] != null) { + stringBuffer + .append(matches2 ? "\"" : "") + .append(results[value].toString()) + .append(matches2 ? "\"" : ""); + value2 = value; + } else { + stringBuffer.append("null"); + value2 = value; + } + if (value2 < results.length - 1) { + stringBuffer.append(", "); + } + } + if (matches) { + stringBuffer.append('}'); + } + return stringBuffer.toString(); + } + + public static final String codeToString( + byte[] values, ConstantPool constantPool, int value, int value2, boolean matches) { + StringBuffer stringBuffer = new StringBuffer(values.length * 20); + ByteSequence byteSequence = new ByteSequence(values); + try { + int value3; + for (int value4 = value3 = 0; value4 < value; value4 = value3) { + value3++; + codeToString(byteSequence, constantPool, matches); + } + for (int index = 0; byteSequence.available() > 0; index++) { + if (value2 < 0 || index < value2) { + String text = fillup(byteSequence.getIndex() + ":", 6, true, ' '); + stringBuffer + .append(text) + .append(codeToString(byteSequence, constantPool, matches)) + .append('\n'); + } + } + } catch (IOException oException) { + System.out.println(stringBuffer.toString()); + oException.printStackTrace(); + throw new ClassFormatException(("Byte code error: " + oException)); + } + return stringBuffer.toString(); + } + + public static final byte calculateValue(String text) { + try { + if (text.charAt(0) != '(') { + throw new ClassFormatException(("Invalid method signature: " + text)); + } else { + return calculateValue2(text.substring(text.lastIndexOf(41) + 1)); + } + } catch (StringIndexOutOfBoundsException stringIndexOutOfBoundsException) { + throw new ClassFormatException(("Invalid method signature: " + text)); + } + } + + public static final String fillup(String text, int value, boolean matches, char value2) { + int value3; + char[] values = new char[(value3 = value - text.length()) < 0 ? 0 : value3]; + int value4; + for (int value5 = value4 = 0; value5 < values.length; value5 = value4) { + int value6 = value4; + value4++; + values[value6] = value2; + } + return matches ? ("" + text + new String(values)) : ("" + new String(values) + text); + } + + public static final String methodSignatureToString( + String text, + String text2, + String text3, + boolean matches, + LocalVariableTable localVariableTable) + throws ClassFormatException { + StringBuffer stringBuffer = new StringBuffer("("); + int value = text3.indexOf("static") >= 0 ? 0 : 1; + String text4; + try { + if (text.charAt(0) != '(') { + throw new ClassFormatException(("Invalid method signature: " + text)); + } + int value2 = 1; + for (String text5 = text; text5.charAt(value2) != ')'; text5 = text) { + String text6 = signatureToString(text.substring(value2), matches); + stringBuffer.append(text6); + if (localVariableTable != null) { + LocalVariable localVariable; + if ((localVariable = localVariableTable.getLocalVariable(value)) != null) { + stringBuffer.append(" ").append(localVariable.getText()); + } + } else { + stringBuffer.append(" arg").append(value); + } + StringBuffer stringBuffer2; + if (!"double".equals(text6) && !"long".equals(text6)) { + value++; + stringBuffer2 = stringBuffer; + } else { + value += 2; + stringBuffer2 = stringBuffer; + } + stringBuffer2.append(", "); + value2 += unwrap(consumed_chars); + } + text4 = signatureToString(text.substring(++value2), matches); + } catch (StringIndexOutOfBoundsException stringIndexOutOfBoundsException) { + throw new ClassFormatException(("Invalid method signature: " + text)); + } + if (stringBuffer.length() > 1) { + stringBuffer.setLength(stringBuffer.length() - 2); + } + stringBuffer.append(")"); + return "" + + text3 + + (text3.length() > 0 ? " " : "") + + text4 + + " " + + text2 + + stringBuffer.toString(); + } + + public static final String getText(int value) { + return (value & 512) != 0 ? "interface" : "class"; + } + + public static final String methodSignatureToString(String text, String text2, String text3) { + return methodSignatureToString(text, text2, text3, true); + } + + public static final String accessToString(int value, boolean matches) { + StringBuffer stringBuffer = new StringBuffer(); + int value2 = 0; + int value3 = (byte) 0; + while (value3 < 16384) { + int value4 = pow2(value2); + if ((value & value4) != 0 && (!matches || value4 != 32 && value4 != 512)) { + stringBuffer.append(Constants.TEXTS9[value2]).append(" "); + } + value2++; + value3 = value4; + } + return stringBuffer.toString().trim(); + } + + public static final String codeToString( + byte[] values, ConstantPool constantPool, int value, int value2) { + return codeToString(values, constantPool, value, value2, true); + } + + public static final String getText(String text, boolean matches) { + return compactClassName(text, "java.lang.", matches); + } + + public static final String codeToString(ByteSequence byteSequence, ConstantPool constantPool) + throws IOException { + return codeToString(byteSequence, constantPool, true); + } + + public static final String createText(String text) { + char[] values = text.toCharArray(); + StringBuffer stringBuffer = new StringBuffer(); + int value; + for (int value2 = value = 0; value2 < values.length; value2 = ++value) { + switch (values[value]) { + case '\n': + stringBuffer.append("\\n"); + break; + case '\r': + stringBuffer.append("\\r"); + break; + case '"': + stringBuffer.append("\\\""); + break; + case '\'': + stringBuffer.append("\\'"); + break; + case '\\': + stringBuffer.append("\\\\"); + break; + default: + stringBuffer.append(values[value]); + } + } + return stringBuffer.toString(); + } + + public static String createText2(String text) { + StringBuffer stringBuffer = new StringBuffer(); + char[] values = text.toCharArray(); + byte value = 0; + byte value2 = 0; + int value3 = -1; + int value4; + label58: + for (int value5 = value4 = 0; value5 < values.length; value5 = ++value4) { + switch (values[value4]) { + case '\t': + case '\n': + case '\f': + case '\r': + case ' ': + if (value != 0) { + value2 = 1; + } + break; + case '[': + if (value == 0) { + throw new RuntimeException(("Illegal type: " + text)); + } + value3 = value4; + break label58; + default: + value = 1; + if (value2 == 0) { + stringBuffer.append(values[value4]); + } + } + } + int value6 = 0; + if (value3 > 0) { + value6 = countBrackets(text.substring(value3)); + } + String text2 = stringBuffer.toString(); + stringBuffer.setLength(0); + int value7; + for (int value8 = value7 = 0; value8 < value6; value8 = value7) { + value7++; + stringBuffer.append('['); + } + byte value9 = 0; + int value10; + for (int value11 = value10 = 4; value11 <= 12 && value9 == 0; value11 = ++value10) { + if (Constants.TEXTS[value10].equals(text2)) { + value9 = 1; + stringBuffer.append(Constants.TEXTS3[value10]); + } + } + if (value9 == 0) { + stringBuffer.append('L').append(text2.replace('.', '/')).append(';'); + } + return stringBuffer.toString(); + } + + public static final boolean isSet(int value, int value2) { + return (value & pow2(value2)) != 0; + } + + public static Attribute[] createAttributes(ConstantPoolGen constantPoolGen, List[] valuess) { + int[] values = new int[valuess.length]; + int value = 0; + int[] values2 = new int[valuess.length]; + int value2 = 0; + try { + int value3; + for (int value4 = value3 = 0; value4 < valuess.length; value4 = ++value3) { + List values3; + if ((values3 = valuess[value3]) != null) { + Iterator iterator2 = values3.iterator(); + while (iterator2.hasNext()) { + if (((AnnotationEntryGen) iterator2.next()).isRuntimeVisible()) { + int value5 = values[value3] + 1; + int value6 = value3; + value++; + values[value6] = value5; + } else { + int value7 = values2[value3] + 1; + int value8 = value3; + value2++; + values2[value8] = value7; + } + } + } + } + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + DataOutputStream dataOutputStream; + (dataOutputStream = new DataOutputStream(byteArrayOutputStream)).writeByte(valuess.length); + int value9; + for (int value10 = value9 = 0; value10 < valuess.length; value10 = ++value9) { + dataOutputStream.writeShort(values[value9]); + if (values[value9] > 0) { + Iterator iterator3 = valuess[value9].iterator(); + while (iterator3.hasNext()) { + AnnotationEntryGen annotationEntryGen; + if ((annotationEntryGen = (AnnotationEntryGen) iterator3.next()).isRuntimeVisible()) { + annotationEntryGen.dump(dataOutputStream); + } + } + } + } + dataOutputStream.close(); + ByteArrayOutputStream byteArrayOutputStream2 = new ByteArrayOutputStream(); + DataOutputStream dataOutputStream2; + (dataOutputStream2 = new DataOutputStream(byteArrayOutputStream2)).writeByte(valuess.length); + int value11; + for (int value12 = value11 = 0; value12 < valuess.length; value12 = ++value11) { + dataOutputStream2.writeShort(values2[value11]); + if (values2[value11] > 0) { + Iterator iterator4 = valuess[value11].iterator(); + while (iterator4.hasNext()) { + AnnotationEntryGen annotationEntryGen2; + if (!(annotationEntryGen2 = (AnnotationEntryGen) iterator4.next()).isRuntimeVisible()) { + annotationEntryGen2.dump(dataOutputStream2); + } + } + } + } + dataOutputStream2.close(); + byte[] values4 = byteArrayOutputStream.toByteArray(); + byte[] values5 = byteArrayOutputStream2.toByteArray(); + int value13 = -1; + int value14 = -1; + if (value > 0) { + value13 = constantPoolGen.addUtf8("RuntimeVisibleParameterAnnotations"); + } + if (value2 > 0) { + value14 = constantPoolGen.addUtf8("RuntimeInvisibleParameterAnnotations"); + } + ArrayList values6 = new ArrayList(); + if (value > 0) { + values6.add( + new RuntimeVisibleParameterAnnotations( + value13, + values4.length, + new DataInputStream(new ByteArrayInputStream(values4)), + constantPoolGen.getConstantPool())); + } + if (value2 > 0) { + values6.add( + new RuntimeInvisibleParameterAnnotations( + value14, + values5.length, + new DataInputStream(new ByteArrayInputStream(values5)), + constantPoolGen.getConstantPool())); + } + return (Attribute[]) values6.toArray(new Attribute[values6.size()]); + } catch (IOException oException) { + System.err.println("IOException whilst processing parameter annotations"); + oException.printStackTrace(); + return null; + } + } + + public static short searchOpcode(String text) { + String text2 = text.toLowerCase(Locale.ENGLISH); + int value; + for (int value2 = value = 0; value2 < Constants.TEXTS8.length; value2 = ++value) { + if (Constants.TEXTS8[value].equals(text2)) { + return (short) value; + } + } + return -1; + } + + public static final String signatureToString(String text, boolean matches) { + wrap(consumed_chars, 1); + try { + switch (text.charAt(0)) { + case 'B': + return "byte"; + case 'C': + return "char"; + case 'D': + return "double"; + case 'E': + case 'G': + case 'H': + case 'K': + case 'M': + case 'N': + case 'O': + case 'P': + case 'Q': + case 'R': + case 'T': + case 'U': + case 'W': + case 'X': + case 'Y': + default: + throw new ClassFormatException(("Invalid signature: `" + text + "'")); + case 'F': + return "float"; + case 'I': + return "int"; + case 'J': + return "long"; + case 'L': + int value; + if ((value = text.indexOf(59)) < 0) { + throw new ClassFormatException(("Invalid signature: " + text)); + } + wrap(consumed_chars, value + 1); + return getText(text.substring(1, value), matches); + case 'S': + return "short"; + case 'V': + return "void"; + case 'Z': + return "boolean"; + case '[': + StringBuffer stringBuffer = new StringBuffer(); + int value2 = 0; + String text2 = text; + while (text2.charAt(value2) == '[') { + value2++; + text2 = text; + stringBuffer.append("[]"); + } + int value3 = value2; + String text3 = signatureToString(text.substring(value2), matches); + int value4 = unwrap(consumed_chars) + value3; + wrap(consumed_chars, value4); + return "" + text3 + stringBuffer.toString(); + } + } catch (StringIndexOutOfBoundsException stringIndexOutOfBoundsException) { + throw new ClassFormatException( + ("Invalid signature: " + stringIndexOutOfBoundsException + ":" + text)); + } + } + + public static final String replace(String text, String text2, String text3) { + String text4 = text; + StringBuffer stringBuffer = new StringBuffer(); + try { + if (text4.indexOf(text2) != -1) { + int value = 0; + String text5 = text4; + int value2; + while ((value2 = text5.indexOf(text2, value)) != -1) { + text5 = text4; + stringBuffer.append(text4.substring(value, value2)); + stringBuffer.append(text3); + value = value2 + text2.length(); + } + stringBuffer.append(text4.substring(value)); + text4 = stringBuffer.toString(); + } + } catch (StringIndexOutOfBoundsException stringIndexOutOfBoundsException) { + System.err.println(stringIndexOutOfBoundsException); + } + return text4; + } + + public static final String getText2(int value) { + return accessToString(value, false); + } + + public static final String[] methodSignatureArgumentTypes(String text, boolean matches) + throws ClassFormatException { + ArrayList values = new ArrayList(); + try { + if (text.charAt(0) != '(') { + throw new ClassFormatException(("Invalid method signature: " + text)); + } + for (int index = 1; text.charAt(index) != ')'; index += unwrap(consumed_chars)) { + values.add(signatureToString(text.substring(index), matches)); + } + } catch (StringIndexOutOfBoundsException stringIndexOutOfBoundsException) { + throw new ClassFormatException(("Invalid method signature: " + text)); + } + return (String[]) values.toArray(new String[values.size()]); + } + + public static byte[] decode(String text, boolean matches) throws IOException { + char[] values = text.toCharArray(); + CharArrayReader charArrayReader = new CharArrayReader(values); + Utility$JavaReader utility$JavaReader = new Utility$JavaReader(charArrayReader); + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + Utility$JavaReader utility$JavaReader2 = utility$JavaReader; + int value; + while ((value = utility$JavaReader2.read()) >= 0) { + utility$JavaReader2 = utility$JavaReader; + byteArrayOutputStream.write(value); + } + byteArrayOutputStream.close(); + charArrayReader.close(); + utility$JavaReader.close(); + byte[] values2 = byteArrayOutputStream.toByteArray(); + if (matches) { + GZIPInputStream gZIPInputStream = new GZIPInputStream(new ByteArrayInputStream(values2)); + byte[] values3 = new byte[values2.length * 3]; + int value2 = 0; + GZIPInputStream gZIPInputStream2 = gZIPInputStream; + int value3; + while ((value3 = gZIPInputStream2.read()) >= 0) { + byte value4 = (byte) value3; + int value5 = value2; + value2++; + gZIPInputStream2 = gZIPInputStream; + values3[value5] = value4; + } + values2 = new byte[value2]; + System.arraycopy(values3, 0, values2, 0, value2); + } + return values2; + } + + public static final short byteToShort(byte value) { + return value < 0 ? (short) (256 + value) : value; + } + + public static int unwrap(ThreadLocal threadLocal) { + return (Integer) threadLocal.get(); + } + + public static final String getText(String text) { + return getText(text, true); + } + + public static final byte calculateValue2(String text) { + try { + switch (text.charAt(0)) { + case 'B': + return 8; + case 'C': + return 5; + case 'D': + return 7; + case 'E': + case 'G': + case 'H': + case 'K': + case 'M': + case 'N': + case 'O': + case 'P': + case 'Q': + case 'R': + case 'U': + case 'W': + case 'X': + case 'Y': + default: + throw new ClassFormatException(("Invalid method signature: " + text)); + case 'F': + return 6; + case 'I': + return 10; + case 'J': + return 11; + case 'L': + case 'T': + return 14; + case 'S': + return 9; + case 'V': + return 12; + case 'Z': + return 4; + case '[': + return 13; + } + } catch (StringIndexOutOfBoundsException stringIndexOutOfBoundsException) { + throw new ClassFormatException(("Invalid method signature: " + text)); + } + } + + public static final String format(int value, int value2, boolean matches, char value3) { + return fillup(Integer.toString(value), value2, matches, value3); + } + + public static final boolean equals(byte[] values, byte[] values2) { + int value; + if ((value = values.length) != values2.length) { + return false; + } + int value2; + for (int value3 = value2 = 0; value3 < value; value3 = ++value2) { + if (values[value2] != values2[value2]) { + return false; + } + } + return true; + } + + public static int countBrackets(String text) { + char[] values = text.toCharArray(); + int value = 0; + byte value2 = 0; + int value3; + for (int value4 = value3 = 0; value4 < values.length; value4 = ++value3) { + switch (values[value3]) { + case '[': + if (value2 != 0) { + throw new RuntimeException(("Illegally nested brackets:" + text)); + } + value2 = 1; + break; + case ']': + if (value2 == 0) { + throw new RuntimeException(("Illegally nested brackets:" + text)); + } + byte value5 = 0; + value++; + value2 = value5; + } + } + if (value2 != 0) { + throw new RuntimeException(("Illegally nested brackets:" + text)); + } else { + return value; + } + } + + public static final int calculateCount(int value, int value2) { + return value | pow2(value2); + } + + public static final void printArray(PrintStream printStream, Object[] results) { + printStream.println(printArray(results, true)); + } + + public static final String getText2(String text) { + return signatureToString(text, true); + } + + public static final int pow2(int value) { + return 1 << value; + } + + public static String encode(byte[] values, boolean matches) throws IOException { + byte[] values2 = values; + if (matches) { + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + GZIPOutputStream gZIPOutputStream; + (gZIPOutputStream = new GZIPOutputStream(byteArrayOutputStream)) + .write(values2, 0, values2.length); + gZIPOutputStream.close(); + byteArrayOutputStream.close(); + values2 = byteArrayOutputStream.toByteArray(); + } + CharArrayWriter charArrayWriter = new CharArrayWriter(); + Utility$JavaWriter utility$JavaWriter = new Utility$JavaWriter(charArrayWriter); + int value; + for (int value2 = value = 0; value2 < values2.length; value2 = value) { + byte value3 = values2[value]; + value++; + utility$JavaWriter.write(value3 & 255); + } + return charArrayWriter.toString(); + } + + public static final String createText(String text, boolean matches) { + try { + return signatureToString(text.substring(text.lastIndexOf(41) + 1), matches); + } catch (StringIndexOutOfBoundsException stringIndexOutOfBoundsException) { + throw new ClassFormatException(("Invalid method signature: " + text)); + } + } + + public static Attribute[] createAttributes(ConstantPoolGen constantPoolGen, List values) { + if (values.size() == 0) { + return null; + } + try { + int value = 0; + int value2 = 0; + int value3; + for (int value4 = value3 = 0; value4 < values.size(); value4 = ++value3) { + if (((AnnotationEntryGen) values.get(value3)).isRuntimeVisible()) { + value++; + } else { + value2++; + } + } + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + ByteArrayOutputStream byteArrayOutputStream2 = new ByteArrayOutputStream(); + DataOutputStream dataOutputStream = new DataOutputStream(byteArrayOutputStream); + DataOutputStream dataOutputStream2 = new DataOutputStream(byteArrayOutputStream2); + int value5 = 0; + dataOutputStream.writeShort(value); + dataOutputStream2.writeShort(value2); + for (int index = 0; value5 < values.size(); value5 = ++index) { + AnnotationEntryGen annotationEntryGen; + if ((annotationEntryGen = (AnnotationEntryGen) values.get(index)).isRuntimeVisible()) { + annotationEntryGen.dump(dataOutputStream); + } else { + annotationEntryGen.dump(dataOutputStream2); + } + } + dataOutputStream.close(); + dataOutputStream2.close(); + byte[] values2 = byteArrayOutputStream.toByteArray(); + byte[] values3 = byteArrayOutputStream2.toByteArray(); + int value6 = -1; + int value7 = -1; + if (values2.length > 2) { + value6 = constantPoolGen.addUtf8("RuntimeVisibleAnnotations"); + } + if (values3.length > 2) { + value7 = constantPoolGen.addUtf8("RuntimeInvisibleAnnotations"); + } + ArrayList values4 = new ArrayList(); + if (values2.length > 2) { + values4.add( + new RuntimeVisibleAnnotations( + value6, + values2.length, + new DataInputStream(new ByteArrayInputStream(values2)), + constantPoolGen.getConstantPool())); + } + if (values3.length > 2) { + values4.add( + new RuntimeInvisibleAnnotations( + value7, + values3.length, + new DataInputStream(new ByteArrayInputStream(values3)), + constantPoolGen.getConstantPool())); + } + return (Attribute[]) values4.toArray(new Attribute[values4.size()]); + } catch (IOException oException) { + System.err.println("IOException whilst processing annotations"); + oException.printStackTrace(); + return null; + } + } + + public static final String methodTypeToSignature(String text, String[] texts) + throws ClassFormatException { + StringBuffer stringBuffer = new StringBuffer("("); + int value; + if (texts != null) { + for (int value2 = value = 0; value2 < texts.length; value2 = value) { + String text2; + if ((text2 = createText2(texts[value])).endsWith("V")) { + throw new ClassFormatException(("Invalid type: " + texts[value])); + } + value++; + stringBuffer.append(text2); + } + } + String text3 = createText2(text); + stringBuffer.append(")").append(text3); + return stringBuffer.toString(); + } + + public static final int calculateCount2(int value, int value2) { + int value3 = pow2(value2); + return (value & value3) == 0 ? value : value ^ value3; + } + + public static final String compactClassName(String text, String text2, boolean matches) { + int size = text2.length(); + String text3 = text.replace('/', '.'); + if (matches && text3.startsWith(text2) && text3.substring(size).indexOf(46) == -1) { + text3 = text3.substring(size); + } + return text3; + } + + public static final void printArray(PrintWriter printWriter, Object[] results) { + printWriter.println(printArray(results, true)); + } + + public static final String[] methodSignatureArgumentTypes(String text) + throws ClassFormatException { + return methodSignatureArgumentTypes(text, true); + } + + public static final String getText3(String text) { + return createText(text, true); + } + + public static final String toHexString(byte[] values) { + StringBuffer stringBuffer = new StringBuffer(); + int value; + for (int value2 = value = 0; value2 < values.length; value2 = ++value) { + short value3; + String text = Integer.toString(value3 = byteToShort(values[value]), 16); + if (value3 < 16) { + stringBuffer.append('0'); + } + stringBuffer.append(text); + if (value < values.length - 1) { + stringBuffer.append(' '); + } + } + return stringBuffer.toString(); + } + + public static final String codeToString( + ByteSequence byteSequence, ConstantPool constantPool, boolean matches) throws IOException { + short value = (short) byteSequence.readUnsignedByte(); + int value2 = 0; + byte value3 = 0; + StringBuffer stringBuffer = new StringBuffer(Constants.TEXTS8[value]); + if (value == 170 || value == 171) { + int value4; + value3 = (byte) ((value4 = byteSequence.getIndex() % 4) == 0 ? 0 : 4 - value4); + int value5; + for (int value6 = value5 = 0; value6 < value3; value6 = ++value5) { + byte value7; + if ((value7 = byteSequence.readByte()) != 0) { + System.err.println( + "Warning: Padding byte != 0 in " + Constants.TEXTS8[value] + ":" + value7); + } + } + value2 = byteSequence.readInt(); + } + switch (value) { + case 18: + int value8 = byteSequence.readUnsignedByte(); + stringBuffer + .append("\t\t") + .append(constantPool.getText(value8, constantPool.getConstant(value8).getTag())) + .append(matches ? (" (" + value8 + ")") : ""); + return stringBuffer.toString(); + case 19: + case 20: + int value9 = byteSequence.readUnsignedShort(); + stringBuffer + .append("\t\t") + .append(constantPool.getText(value9, constantPool.getConstant(value9).getTag())) + .append(matches ? (" (" + value9 + ")") : ""); + return stringBuffer.toString(); + case 21: + case 22: + case 23: + case 24: + case 25: + case 54: + case 55: + case 56: + case 57: + case 58: + case 169: + int value10; + StringBuffer stringBuffer2; + if (wide) { + value10 = byteSequence.readUnsignedShort(); + wide = false; + stringBuffer2 = stringBuffer; + } else { + value10 = byteSequence.readUnsignedByte(); + stringBuffer2 = stringBuffer; + } + stringBuffer2.append("\t\t%").append(value10); + return stringBuffer.toString(); + case 26: + case 27: + case 28: + case 29: + case 30: + case 31: + case 32: + case 33: + case 34: + case 35: + case 36: + case 37: + case 38: + case 39: + case 40: + case 41: + case 42: + case 43: + case 44: + case 45: + case 46: + case 47: + case 48: + case 49: + case 50: + case 51: + case 52: + case 53: + case 59: + case 60: + case 61: + case 62: + case 63: + case 64: + case 65: + case 66: + case 67: + case 68: + case 69: + case 70: + case 71: + case 72: + case 73: + case 74: + case 75: + case 76: + case 77: + case 78: + case 79: + case 80: + case 81: + case 82: + case 83: + case 84: + case 85: + case 86: + case 87: + case 88: + case 89: + case 90: + case 91: + case 92: + case 93: + case 94: + case 95: + case 96: + case 97: + case 98: + case 99: + case 100: + case 101: + case 102: + case 103: + case 104: + case 105: + case 106: + case 107: + case 108: + case 109: + case 110: + case 111: + case 112: + case 113: + case 114: + case 115: + case 116: + case 117: + case 118: + case 119: + case 120: + case 121: + case 122: + case 123: + case 124: + case 125: + case 126: + case 127: + case 128: + case 129: + case 130: + case 131: + case 133: + case 134: + case 135: + case 136: + case 137: + case 138: + case 139: + case 140: + case 141: + case 142: + case 143: + case 144: + case 145: + case 146: + case 147: + case 148: + case 149: + case 150: + case 151: + case 152: + case 172: + case 173: + case 174: + case 175: + case 176: + case 177: + case 190: + case 191: + case 194: + case 195: + default: + int value11; + if (Constants.NO_OF_OPERANDS[value] > 0) { + for (int value12 = value11 = 0; + value12 < Constants.TYPE_OF_OPERANDS[value].length; + value12 = ++value11) { + stringBuffer.append("\t\t"); + switch (Constants.TYPE_OF_OPERANDS[value][value11]) { + case 8: + stringBuffer.append(byteSequence.readByte()); + break; + case 9: + stringBuffer.append(byteSequence.readShort()); + break; + case 10: + stringBuffer.append(byteSequence.readInt()); + break; + default: + System.err.println("Unreachable default case reached!"); + System.exit(-1); + } + } + } + break; + case 132: + short value13; + int value14; + StringBuffer stringBuffer3; + if (wide) { + value14 = byteSequence.readUnsignedShort(); + stringBuffer3 = stringBuffer; + value13 = byteSequence.readShort(); + wide = false; + } else { + value14 = byteSequence.readUnsignedByte(); + stringBuffer3 = stringBuffer; + value13 = byteSequence.readByte(); + } + stringBuffer3.append("\t\t%").append(value14).append("\t").append(value13); + return stringBuffer.toString(); + case 153: + case 154: + case 155: + case 156: + case 157: + case 158: + case 159: + case 160: + case 161: + case 162: + case 163: + case 164: + case 165: + case 166: + case 167: + case 168: + case 198: + case 199: + stringBuffer.append("\t\t#").append(byteSequence.getIndex() - 1 + byteSequence.readShort()); + return stringBuffer.toString(); + case 170: + int value15 = byteSequence.readInt(); + int value16 = byteSequence.readInt(); + int value17 = byteSequence.getIndex() - 12 - value3 - 1; + int value18 = value2 + value17; + stringBuffer + .append("\tdefault = ") + .append(value18) + .append(", low = ") + .append(value15) + .append(", high = ") + .append(value16) + .append("("); + int[] values = new int[value16 - value15 + 1]; + int value19 = 0; + for (int value20 = value19; value20 < values.length; value20 = ++value19) { + values[value19] = value17 + byteSequence.readInt(); + stringBuffer.append(values[value19]); + if (value19 < values.length - 1) { + stringBuffer.append(", "); + } + } + stringBuffer.append(")"); + return stringBuffer.toString(); + case 171: + int value21 = byteSequence.readInt(); + int value22 = byteSequence.getIndex() - 8 - value3 - 1; + int[] values2 = new int[value21]; + int[] values3 = new int[value21]; + int value23 = value2 + value22; + stringBuffer + .append("\tdefault = ") + .append(value23) + .append(", npairs = ") + .append(value21) + .append(" ("); + int value24 = 0; + for (int value25 = value24; value25 < value21; value25 = ++value24) { + values2[value24] = byteSequence.readInt(); + values3[value24] = value22 + byteSequence.readInt(); + stringBuffer + .append("(") + .append(values2[value24]) + .append(", ") + .append(values3[value24]) + .append(")"); + if (value24 < value21 - 1) { + stringBuffer.append(", "); + } + } + stringBuffer.append(")"); + return stringBuffer.toString(); + case 178: + case 179: + case 180: + case 181: + int value26 = byteSequence.readUnsignedShort(); + stringBuffer + .append("\t\t") + .append(constantPool.getText(value26, (byte) 9)) + .append(matches ? (" (" + value26 + ")") : ""); + return stringBuffer.toString(); + case 182: + case 183: + case 184: + int value27 = byteSequence.readUnsignedShort(); + stringBuffer + .append("\t") + .append(constantPool.getText(value27, (byte) 10)) + .append(matches ? (" (" + value27 + ")") : ""); + return stringBuffer.toString(); + case 185: + int value28 = byteSequence.readUnsignedShort(); + int value29 = byteSequence.readUnsignedByte(); + stringBuffer + .append("\t") + .append(constantPool.getText(value28, (byte) 11)) + .append(matches ? (" (" + value28 + ")\t") : "") + .append(value29) + .append("\t") + .append(byteSequence.readUnsignedByte()); + return stringBuffer.toString(); + case 186: + int value30 = byteSequence.readUnsignedShort(); + byteSequence.readUnsignedShort(); + ConstantInvokeDynamic constantInvokeDynamic = + (ConstantInvokeDynamic) constantPool.getConstant(value30, (byte) 18); + stringBuffer + .append("\t") + .append(".") + .append( + constantPool.getText( + constantInvokeDynamic.getBootstrapMethodAttrIndex2(), (byte) 12)); + if (matches) { + stringBuffer.append( + " (" + value30 + "/" + constantInvokeDynamic.getBootstrapMethodAttrIndex2() + ")"); + return stringBuffer.toString(); + } + break; + case 187: + case 192: + stringBuffer.append("\t"); + case 193: + int value31 = byteSequence.readUnsignedShort(); + stringBuffer + .append("\t<") + .append(constantPool.getText(value31, (byte) 7)) + .append(">") + .append(matches ? (" (" + value31 + ")") : ""); + return stringBuffer.toString(); + case 188: + stringBuffer.append("\t\t<").append(Constants.TEXTS[byteSequence.readByte()]).append(">"); + return stringBuffer.toString(); + case 189: + int value32 = byteSequence.readUnsignedShort(); + stringBuffer + .append("\t\t<") + .append(getText(constantPool.createText(value32, (byte) 7), false)) + .append(">") + .append(matches ? (" (" + value32 + ")") : ""); + return stringBuffer.toString(); + case 196: + wide = true; + stringBuffer.append("\t(wide)"); + return stringBuffer.toString(); + case 197: + int value33 = byteSequence.readUnsignedShort(); + int value34 = byteSequence.readUnsignedByte(); + stringBuffer + .append("\t<") + .append(getText(constantPool.createText(value33, (byte) 7), false)) + .append(">\t") + .append(value34) + .append(matches ? (" (" + value33 + ")") : ""); + return stringBuffer.toString(); + case 200: + case 201: + stringBuffer.append("\t\t#").append(byteSequence.getIndex() - 1 + byteSequence.readInt()); + return stringBuffer.toString(); + } + return stringBuffer.toString(); + } + + public static void wrap(ThreadLocal threadLocal, int value) { + threadLocal.set(new Integer(value)); + } + + public static final String printArray(Object[] results, boolean matches) { + return printArray(results, matches, false); + } + + public static final String printArray(Object[] results) { + return printArray(results, true); + } + + public static boolean isJavaIdentifierPart(char value) { + return value >= 'a' && value <= 'z' + || value >= 'A' && value <= 'Z' + || value >= '0' && value <= '9' + || value == '_'; + } + + public static final String methodSignatureToString( + String text, String text2, String text3, boolean matches) { + return methodSignatureToString(text, text2, text3, matches, null); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/classfile/Visitor.java b/src/main/java/com/allatori/lib/bcel/classfile/Visitor.java new file mode 100644 index 0000000..ef729ad --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/classfile/Visitor.java @@ -0,0 +1,80 @@ +package com.allatori.lib.bcel.classfile; + +public interface Visitor { + + void visitEnclosingMethod(EnclosingMethod enclosingMethod); + + void visitStackMap(StackMap stackMap); + + void visitConstantValue(ConstantValue constantValue); + + void visitConstantNameAndType(ConstantNameAndType constantNameAndType); + + void visitInnerClasses(InnerClasses innerClasses); + + void visitInnerClass(InnerClass innerClass); + + void visitConstantPool(ConstantPool constantPool); + + void visitCode(Code code); + + void visitDeprecated(Deprecated deprecated); + + void visitConstantInterfaceMethodref(ConstantInterfaceMethodref constantInterfaceMethodref); + + void visitCodeException(CodeException codeException); + + void visitConstantClass(ConstantClass constantClass); + + void visitExceptionTable(ExceptionTable exceptionTable); + + void visitStackMapEntry(StackMapEntry stackMapEntry); + + void visitLineNumber(LineNumber lineNumber); + + void visitUnknown(Unknown unknown); + + void visitSourceFile(SourceFile sourceFile); + + void visitConstantMethodref(ConstantMethodref constantMethodref); + + void visitConstantString(ConstantString constantString); + + void visitConstantLong(ConstantLong constantLong); + + void visitAnnotationEntry(AnnotationEntry annotationEntry); + + void visitLineNumberTable(LineNumberTable lineNumberTable); + + void visitConstantUtf8(ConstantUtf8 constantUtf8); + + void visitLocalVariableTypeTable(LocalVariableTypeTable localVariableTypeTable); + + void visitSynthetic(Synthetic synthetic); + + void visitConstantFieldref(ConstantFieldref constantFieldref); + + void visitLocalVariableTable(LocalVariableTable localVariableTable); + + void visitAnnotation(Annotations annotations); + + void visitLocalVariable(LocalVariable localVariable); + + void visitAnnotationDefault(AnnotationDefault annotationDefault); + + void visitMethod(Method method); + + void visitJavaClass(JavaClass javaClass); + + void visitParameterAnnotation(ParameterAnnotations parameterAnnotations); + + void visitConstantInteger(ConstantInteger constantInteger); + + void visitConstantFloat(ConstantFloat constantFloat); + + void visitConstantDouble(ConstantDouble constantDouble); + + void visitSignature(Signature signature); + + void visitField(Field field); +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/AALOAD.java b/src/main/java/com/allatori/lib/bcel/generic/AALOAD.java new file mode 100644 index 0000000..103cd17 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/AALOAD.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class AALOAD extends ArrayInstruction implements StackProducer { + + @Override + public void accept(Visitor visitor) { + visitor.visitStackProducer(this); + visitor.visitExceptionThrower(this); + visitor.visitTypedInstruction(this); + visitor.visitArrayInstruction(this); + visitor.visitAALOAD(this); + } + + public AALOAD() { + super((short) 50); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/AASTORE.java b/src/main/java/com/allatori/lib/bcel/generic/AASTORE.java new file mode 100644 index 0000000..6c6aff5 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/AASTORE.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class AASTORE extends ArrayInstruction implements StackConsumer { + + @Override + public void accept(Visitor visitor) { + visitor.visitStackConsumer(this); + visitor.visitExceptionThrower(this); + visitor.visitTypedInstruction(this); + visitor.visitArrayInstruction(this); + visitor.visitAASTORE(this); + } + + public AASTORE() { + super((short) 83); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/ACONST_NULL.java b/src/main/java/com/allatori/lib/bcel/generic/ACONST_NULL.java new file mode 100644 index 0000000..ae14640 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/ACONST_NULL.java @@ -0,0 +1,21 @@ +package com.allatori.lib.bcel.generic; + +public class ACONST_NULL extends Instruction implements PushInstruction, TypedInstruction { + + public ACONST_NULL() { + super((short) 1, (short) 1); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitStackProducer(this); + visitor.visitPushInstruction(this); + visitor.visitTypedInstruction(this); + visitor.visitACONST_NULL(this); + } + + @Override + public Type getType(ConstantPoolGen constantPoolGen) { + return Type.NULL; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/ALOAD.java b/src/main/java/com/allatori/lib/bcel/generic/ALOAD.java new file mode 100644 index 0000000..c4bcbbe --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/ALOAD.java @@ -0,0 +1,18 @@ +package com.allatori.lib.bcel.generic; + +public class ALOAD extends LoadInstruction { + + public ALOAD(int value) { + super((short) 25, (short) 42, value); + } + + @Override + public void accept(Visitor visitor) { + super.accept(visitor); + visitor.visitALOAD(this); + } + + public ALOAD() { + super((short) 25, (short) 42); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/ANEWARRAY.java b/src/main/java/com/allatori/lib/bcel/generic/ANEWARRAY.java new file mode 100644 index 0000000..a937ca2 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/ANEWARRAY.java @@ -0,0 +1,41 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.ExceptionConstants; + +public class ANEWARRAY extends CPInstruction + implements LoadClass, AllocationInstruction, ExceptionThrower, StackConsumer, StackProducer { + + @Override + public ObjectType getLoadClassType(ConstantPoolGen constantPoolGen) { + Type type; + if ((type = this.getType(constantPoolGen)) instanceof ArrayType) { + type = ((ArrayType) type).getBasicType(); + } + return type instanceof ObjectType ? (ObjectType) type : null; + } + + @Override + public Class[] getExceptions() { + Class[] classs = new Class[1 + ExceptionConstants.TYPES5.length]; + System.arraycopy(ExceptionConstants.TYPES5, 0, classs, 0, ExceptionConstants.TYPES5.length); + classs[ExceptionConstants.TYPES5.length] = ExceptionConstants.TYPE11; + return classs; + } + + @Override + public void accept(Visitor visitor) { + visitor.visitLoadClass(this); + visitor.visitAllocationInstruction(this); + visitor.visitExceptionThrower(this); + visitor.visitStackProducer(this); + visitor.visitTypedInstruction(this); + visitor.visitCPInstruction(this); + visitor.visitANEWARRAY(this); + } + + public ANEWARRAY() {} + + public ANEWARRAY(int value) { + super((short) 189, value); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/ARETURN.java b/src/main/java/com/allatori/lib/bcel/generic/ARETURN.java new file mode 100644 index 0000000..3a4b224 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/ARETURN.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class ARETURN extends ReturnInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitExceptionThrower(this); + visitor.visitTypedInstruction(this); + visitor.visitStackConsumer(this); + visitor.visitReturnInstruction(this); + visitor.visitARETURN(this); + } + + public ARETURN() { + super((short) 176); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/ARRAYLENGTH.java b/src/main/java/com/allatori/lib/bcel/generic/ARRAYLENGTH.java new file mode 100644 index 0000000..1d51461 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/ARRAYLENGTH.java @@ -0,0 +1,22 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.ExceptionConstants; + +public class ARRAYLENGTH extends Instruction implements ExceptionThrower, StackProducer { + + @Override + public Class[] getExceptions() { + return new Class[] {ExceptionConstants.TYPE3}; + } + + @Override + public void accept(Visitor visitor) { + visitor.visitExceptionThrower(this); + visitor.visitStackProducer(this); + visitor.visitARRAYLENGTH(this); + } + + public ARRAYLENGTH() { + super((short) 190, (short) 1); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/ASTORE.java b/src/main/java/com/allatori/lib/bcel/generic/ASTORE.java new file mode 100644 index 0000000..919e1f3 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/ASTORE.java @@ -0,0 +1,18 @@ +package com.allatori.lib.bcel.generic; + +public class ASTORE extends StoreInstruction { + + @Override + public void accept(Visitor visitor) { + super.accept(visitor); + visitor.visitASTORE(this); + } + + public ASTORE(int value) { + super((short) 58, (short) 75, value); + } + + public ASTORE() { + super((short) 58, (short) 75); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/ATHROW.java b/src/main/java/com/allatori/lib/bcel/generic/ATHROW.java new file mode 100644 index 0000000..73507db --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/ATHROW.java @@ -0,0 +1,22 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.ExceptionConstants; + +public class ATHROW extends Instruction implements UnconditionalBranch, ExceptionThrower { + + @Override + public Class[] getExceptions() { + return new Class[] {ExceptionConstants.TYPE10}; + } + + @Override + public void accept(Visitor visitor) { + visitor.visitUnconditionalBranch(this); + visitor.visitExceptionThrower(this); + visitor.visitATHROW(this); + } + + public ATHROW() { + super((short) 191, (short) 1); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/AllocationInstruction.java b/src/main/java/com/allatori/lib/bcel/generic/AllocationInstruction.java new file mode 100644 index 0000000..b84de65 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/AllocationInstruction.java @@ -0,0 +1,3 @@ +package com.allatori.lib.bcel.generic; + +public interface AllocationInstruction {} diff --git a/src/main/java/com/allatori/lib/bcel/generic/AnnotationElementValueGen.java b/src/main/java/com/allatori/lib/bcel/generic/AnnotationElementValueGen.java new file mode 100644 index 0000000..9394c94 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/AnnotationElementValueGen.java @@ -0,0 +1,58 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.classfile.AnnotationElementValue; +import com.allatori.lib.bcel.classfile.ElementValue; +import java.io.DataOutputStream; +import java.io.IOException; + +public class AnnotationElementValueGen extends ElementValueGen { + + public AnnotationEntryGen a; + + public AnnotationEntryGen getAnnotation() { + return this.a; + } + + @Override + public String stringifyValue() { + throw new RuntimeException("Not implemented yet"); + } + + public AnnotationElementValueGen( + AnnotationElementValue annotationElementValue, + ConstantPoolGen constantPoolGen, + boolean matches) { + super(64, constantPoolGen); + this.a = + new AnnotationEntryGen( + annotationElementValue.getAnnotationEntry(), constantPoolGen, matches); + } + + public AnnotationElementValueGen( + int value, AnnotationEntryGen annotationEntryGen, ConstantPoolGen constantPoolGen) { + super(value, constantPoolGen); + if (value != 64) { + throw new RuntimeException( + "Only element values of type annotation can be built with this ctor"); + } + this.a = annotationEntryGen; + } + + @Override + public void dump(DataOutputStream dataOutputStream) throws IOException { + dataOutputStream.writeByte(this.type); + this.a.dump(dataOutputStream); + } + + public AnnotationElementValueGen( + AnnotationEntryGen annotationEntryGen, ConstantPoolGen constantPoolGen) { + super(64, constantPoolGen); + this.a = annotationEntryGen; + } + + @Override + public ElementValue getElementValue() { + return new AnnotationElementValue( + this.type, this.a.getAnnotation(), this.cpGen.getConstantPool()); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/AnnotationEntryGen.java b/src/main/java/com/allatori/lib/bcel/generic/AnnotationEntryGen.java new file mode 100644 index 0000000..f5e4889 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/AnnotationEntryGen.java @@ -0,0 +1,161 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.classfile.AnnotationEntry; +import com.allatori.lib.bcel.classfile.ConstantUtf8; +import com.allatori.lib.bcel.classfile.ElementValuePair; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class AnnotationEntryGen { + + public boolean isRuntimeVisible; + + public List evs; + + public int typeIndex; + + public ConstantPoolGen cpool; + + public int getTypeIndex() { + return this.typeIndex; + } + + public boolean isRuntimeVisible() { + return this.isRuntimeVisible; + } + + public List getValues() { + return this.evs; + } + + public AnnotationEntry getAnnotation() { + AnnotationEntry annotationEntry = + new AnnotationEntry(this.typeIndex, this.cpool.getConstantPool(), this.isRuntimeVisible); + Iterator iterator2; + Iterator iterator3 = iterator2 = this.evs.iterator(); + while (iterator3.hasNext()) { + ElementValuePairGen elementValuePairGen = (ElementValuePairGen) iterator2.next(); + iterator3 = iterator2; + annotationEntry.addElementNameValuePair(elementValuePairGen.getElementNameValuePair()); + } + return annotationEntry; + } + + public void isRuntimeVisible(boolean isRuntimeVisible) { + this.isRuntimeVisible = isRuntimeVisible; + } + + public final String getText() { + return this.getText2(); + } + + public AnnotationEntryGen(ConstantPoolGen constantPoolGen) { + super(); + this.isRuntimeVisible = false; + this.cpool = constantPoolGen; + } + + public final String getText2() { + return ((ConstantUtf8) this.cpool.getConstant(this.typeIndex)).getBytes(); + } + + public String toShortString() { + StringBuffer stringBuffer = new StringBuffer(); + stringBuffer.append("@" + this.getText() + "("); + int value = 0; + for (int value2 = value; value2 < this.evs.size(); value2 = ++value) { + stringBuffer.append(this.evs.get(value)); + if (value + 1 < this.evs.size()) { + stringBuffer.append(","); + } + } + stringBuffer.append(")"); + return stringBuffer.toString(); + } + + public void dump(DataOutputStream dataOutputStream) throws IOException { + int value = 0; + dataOutputStream.writeShort(this.typeIndex); + dataOutputStream.writeShort(this.evs.size()); + for (int index = 0; value < this.evs.size(); value = index) { + Object result = this.evs.get(index); + index++; + ((ElementValuePairGen) result).dump(dataOutputStream); + } + } + + public AnnotationEntryGen( + AnnotationEntry annotationEntry, ConstantPoolGen constantPoolGen, boolean matches) { + super(); + this.isRuntimeVisible = false; + this.cpool = constantPoolGen; + AnnotationEntryGen annotationEntryGen; + if (matches) { + annotationEntryGen = this; + this.typeIndex = constantPoolGen.addUtf8(annotationEntry.getText()); + } else { + annotationEntryGen = this; + this.typeIndex = annotationEntry.getCount2(); + } + annotationEntryGen.isRuntimeVisible = annotationEntry.isRuntimeVisible(); + this.evs = this.copyValues(annotationEntry.getElementValuePairs(), constantPoolGen, matches); + } + + public void addElementNameValuePair(ElementValuePairGen elementValuePairGen) { + if (this.evs == null) { + this.evs = new ArrayList(); + } + this.evs.add(elementValuePairGen); + } + + public void setTypeIndex(int typeIndex) { + this.typeIndex = typeIndex; + } + + public AnnotationEntryGen( + ObjectType objectType, List evs, boolean isRuntimeVisible, ConstantPoolGen constantPoolGen) { + super(); + this.isRuntimeVisible = false; + this.cpool = constantPoolGen; + this.typeIndex = constantPoolGen.addUtf8(objectType.getSignature()); + this.evs = evs; + this.isRuntimeVisible = isRuntimeVisible; + } + + public List copyValues( + ElementValuePair[] elementValuePairs, ConstantPoolGen constantPoolGen, boolean matches) { + ArrayList values = new ArrayList(); + int value = elementValuePairs.length; + int value2; + for (int value3 = value2 = 0; value3 < value; value3 = value2) { + ElementValuePair elementValuePair = elementValuePairs[value2]; + value2++; + values.add(new ElementValuePairGen(elementValuePair, constantPoolGen, matches)); + } + return values; + } + + public static AnnotationEntryGen createAnnotationEntryGen( + DataInputStream dataInputStream, ConstantPoolGen constantPoolGen, boolean matches) + throws IOException { + AnnotationEntryGen annotationEntryGen; + (annotationEntryGen = new AnnotationEntryGen(constantPoolGen)).typeIndex = + dataInputStream.readUnsignedShort(); + int value = dataInputStream.readUnsignedShort(); + int value2; + for (int value3 = value2 = 0; value3 < value; value3 = value2) { + int value4 = dataInputStream.readUnsignedShort(); + ElementValueGen elementValueGen = + ElementValueGen.createElementValueGen(dataInputStream, constantPoolGen); + value2++; + annotationEntryGen.addElementNameValuePair( + new ElementValuePairGen(value4, elementValueGen, constantPoolGen)); + } + annotationEntryGen.isRuntimeVisible(matches); + return annotationEntryGen; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/ArithmeticInstruction.java b/src/main/java/com/allatori/lib/bcel/generic/ArithmeticInstruction.java new file mode 100644 index 0000000..9799d76 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/ArithmeticInstruction.java @@ -0,0 +1,59 @@ +package com.allatori.lib.bcel.generic; + +public abstract class ArithmeticInstruction extends Instruction + implements TypedInstruction, StackProducer, StackConsumer { + + @Override + public Type getType(ConstantPoolGen constantPoolGen) { + switch (this.opcode) { + case 96: + case 100: + case 104: + case 108: + case 112: + case 116: + case 120: + case 122: + case 124: + case 126: + case 128: + case 130: + return Type.INT; + case 97: + case 101: + case 105: + case 109: + case 113: + case 117: + case 121: + case 123: + case 125: + case 127: + case 129: + case 131: + return Type.LONG; + case 98: + case 102: + case 106: + case 110: + case 114: + case 118: + return Type.FLOAT; + case 99: + case 103: + case 107: + case 111: + case 115: + case 119: + return Type.DOUBLE; + default: + throw new ClassGenException(("Unknown type " + this.opcode)); + } + } + + public ArithmeticInstruction() {} + + public ArithmeticInstruction(short value) { + super(value, (short) 1); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/ArrayElementValueGen.java b/src/main/java/com/allatori/lib/bcel/generic/ArrayElementValueGen.java new file mode 100644 index 0000000..cb99090 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/ArrayElementValueGen.java @@ -0,0 +1,107 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.classfile.ArrayElementValue; +import com.allatori.lib.bcel.classfile.ElementValue; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class ArrayElementValueGen extends ElementValueGen { + + public List evalues; + + @Override + public ElementValue getElementValue() { + ElementValue[] elementValues = new ElementValue[this.evalues.size()]; + int value = 0; + Iterator iterator2; + Iterator iterator3 = iterator2 = this.evalues.iterator(); + while (iterator3.hasNext()) { + ElementValueGen elementValueGen = (ElementValueGen) iterator2.next(); + ElementValue elementValue = elementValueGen.getElementValue(); + int value2 = value; + Iterator iterator4 = iterator2; + value++; + iterator3 = iterator4; + elementValues[value2] = elementValue; + } + return new ArrayElementValue(this.type, elementValues, this.cpGen.getConstantPool()); + } + + public int getElementValuesSize() { + return this.evalues.size(); + } + + public ArrayElementValueGen( + int value, ElementValue[] elementValues, ConstantPoolGen constantPoolGen) { + super(value, constantPoolGen); + if (value != 91) { + throw new RuntimeException("Only element values of type array can be built with this ctor"); + } + this.evalues = new ArrayList(); + int value2; + for (int value3 = value2 = 0; value3 < elementValues.length; value3 = value2) { + int value4 = value2; + List values = this.evalues; + value2++; + values.add(elementValues[value4]); + } + } + + public void addElement(ElementValueGen elementValueGen) { + this.evalues.add(elementValueGen); + } + + public ArrayElementValueGen(ConstantPoolGen constantPoolGen) { + super(91, constantPoolGen); + this.evalues = new ArrayList(); + } + + public List getElementValues() { + return this.evalues; + } + + @Override + public void dump(DataOutputStream dataOutputStream) throws IOException { + dataOutputStream.writeByte(this.type); + dataOutputStream.writeShort(this.evalues.size()); + Iterator iterator2; + for (Iterator iterator3 = iterator2 = this.evalues.iterator(); + iterator3.hasNext(); + iterator3 = iterator2) { + ((ElementValueGen) iterator2.next()).dump(dataOutputStream); + } + } + + @Override + public String stringifyValue() { + StringBuffer stringBuffer; + (stringBuffer = new StringBuffer()).append("["); + Iterator iterator2 = this.evalues.iterator(); + while (iterator2.hasNext()) { + ElementValueGen elementValueGen = (ElementValueGen) iterator2.next(); + stringBuffer.append(elementValueGen.stringifyValue()); + if (iterator2.hasNext()) { + stringBuffer.append(","); + } + } + stringBuffer.append("]"); + return stringBuffer.toString(); + } + + public ArrayElementValueGen( + ArrayElementValue arrayElementValue, ConstantPoolGen constantPoolGen, boolean matches) { + super(91, constantPoolGen); + this.evalues = new ArrayList(); + ElementValue[] elementValuesArray = arrayElementValue.getElementValuesArray(); + int value; + for (int value2 = value = 0; value2 < elementValuesArray.length; value2 = value) { + ElementValue elementValue = elementValuesArray[value]; + List values = this.evalues; + value++; + values.add(ElementValueGen.copy(elementValue, constantPoolGen, matches)); + } + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/ArrayInstruction.java b/src/main/java/com/allatori/lib/bcel/generic/ArrayInstruction.java new file mode 100644 index 0000000..e82936a --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/ArrayInstruction.java @@ -0,0 +1,75 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.ExceptionConstants; + +public abstract class ArrayInstruction extends Instruction + implements ExceptionThrower, TypedInstruction { + + @Override + public Class[] getExceptions() { + return ExceptionConstants.TYPES3; + } + + @Override + public Type getType(ConstantPoolGen constantPoolGen) { + switch (this.opcode) { + case 46: + case 79: + return Type.INT; + case 47: + case 80: + return Type.LONG; + case 48: + case 81: + return Type.FLOAT; + case 49: + case 82: + return Type.DOUBLE; + case 50: + case 83: + return Type.OBJECT; + case 51: + case 84: + return Type.BYTE; + case 52: + case 85: + return Type.CHAR; + case 53: + case 86: + return Type.SHORT; + case 54: + case 55: + case 56: + case 57: + case 58: + case 59: + case 60: + case 61: + case 62: + case 63: + case 64: + case 65: + case 66: + case 67: + case 68: + case 69: + case 70: + case 71: + case 72: + case 73: + case 74: + case 75: + case 76: + case 77: + case 78: + default: + throw new ClassGenException(("Oops: unknown case in switch" + this.opcode)); + } + } + + public ArrayInstruction(short value) { + super(value, (short) 1); + } + + public ArrayInstruction() {} +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/ArrayType.java b/src/main/java/com/allatori/lib/bcel/generic/ArrayType.java new file mode 100644 index 0000000..c7539f8 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/ArrayType.java @@ -0,0 +1,73 @@ +package com.allatori.lib.bcel.generic; + +public final class ArrayType extends ReferenceType { + + public Type basic_type; + + public int dimensions; + + public Type getBasicType() { + return this.basic_type; + } + + public Type getElementType() { + return this.dimensions == 1 + ? this.basic_type + : new ArrayType(this.basic_type, this.dimensions - 1); + } + + public ArrayType(String text, int value) { + this(new ObjectType(text), value); + } + + public ArrayType(Type type, int dimensions) { + super((byte) 13, ""); + if (dimensions >= 1 && dimensions <= 255) { + switch (type.getType()) { + case 12: + throw new ClassGenException("Invalid type: void[]"); + case 13: + ArrayType arrayType; + ArrayType arrayType2 = arrayType = (ArrayType) type; + this.dimensions = dimensions + arrayType.dimensions; + this.basic_type = arrayType2.basic_type; + break; + default: + this.dimensions = dimensions; + this.basic_type = type; + } + StringBuffer stringBuffer = new StringBuffer(); + int value2; + for (int value3 = value2 = 0; value3 < this.dimensions; value3 = value2) { + value2++; + stringBuffer.append('['); + } + stringBuffer.append(this.basic_type.getSignature()); + this.signature = stringBuffer.toString(); + } else { + throw new ClassGenException(("Invalid number of dimensions: " + dimensions)); + } + } + + @Override + public boolean equals(Object result) { + ArrayType arrayType; + return result instanceof ArrayType + ? (arrayType = (ArrayType) result).dimensions == this.dimensions + && arrayType.basic_type.equals(this.basic_type) + : false; + } + + public ArrayType(byte value, int value2) { + this(BasicType.getType(value), value2); + } + + @Override + public int hashCode() { + return this.basic_type.hashCode() ^ this.dimensions; + } + + public int getDimensions() { + return this.dimensions; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/BALOAD.java b/src/main/java/com/allatori/lib/bcel/generic/BALOAD.java new file mode 100644 index 0000000..2bd3e7b --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/BALOAD.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class BALOAD extends ArrayInstruction implements StackProducer { + + @Override + public void accept(Visitor visitor) { + visitor.visitStackProducer(this); + visitor.visitExceptionThrower(this); + visitor.visitTypedInstruction(this); + visitor.visitArrayInstruction(this); + visitor.visitBALOAD(this); + } + + public BALOAD() { + super((short) 51); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/BASTORE.java b/src/main/java/com/allatori/lib/bcel/generic/BASTORE.java new file mode 100644 index 0000000..89bdd98 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/BASTORE.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class BASTORE extends ArrayInstruction implements StackConsumer { + + @Override + public void accept(Visitor visitor) { + visitor.visitStackConsumer(this); + visitor.visitExceptionThrower(this); + visitor.visitTypedInstruction(this); + visitor.visitArrayInstruction(this); + visitor.visitBASTORE(this); + } + + public BASTORE() { + super((short) 84); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/BIPUSH.java b/src/main/java/com/allatori/lib/bcel/generic/BIPUSH.java new file mode 100644 index 0000000..7427c8a --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/BIPUSH.java @@ -0,0 +1,53 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.util.ByteSequence; +import java.io.DataOutputStream; +import java.io.IOException; + +public class BIPUSH extends Instruction implements ConstantPushInstruction { + + public byte b; + + @Override + public void initFromFile(ByteSequence byteSequence, boolean matches) throws IOException { + this.length = 2; + this.b = byteSequence.readByte(); + } + + public BIPUSH(byte b) { + super((short) 16, (short) 2); + this.b = b; + } + + @Override + public Number getValue() { + return new Integer(this.b); + } + + @Override + public void dump(DataOutputStream dataOutputStream) throws IOException { + super.dump(dataOutputStream); + dataOutputStream.writeByte(this.b); + } + + @Override + public String toString(boolean matches) { + return "" + super.toString(matches) + " " + this.b; + } + + public BIPUSH() {} + + @Override + public void accept(Visitor visitor) { + visitor.visitPushInstruction(this); + visitor.visitStackProducer(this); + visitor.visitTypedInstruction(this); + visitor.visitConstantPushInstruction(this); + visitor.visitBIPUSH(this); + } + + @Override + public Type getType(ConstantPoolGen constantPoolGen) { + return Type.BYTE; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/BREAKPOINT.java b/src/main/java/com/allatori/lib/bcel/generic/BREAKPOINT.java new file mode 100644 index 0000000..91387aa --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/BREAKPOINT.java @@ -0,0 +1,13 @@ +package com.allatori.lib.bcel.generic; + +public class BREAKPOINT extends Instruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitBREAKPOINT(this); + } + + public BREAKPOINT() { + super((short) 202, (short) 1); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/BasicType.java b/src/main/java/com/allatori/lib/bcel/generic/BasicType.java new file mode 100644 index 0000000..38ffc30 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/BasicType.java @@ -0,0 +1,48 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.Constants; + +public final class BasicType extends Type { + + public BasicType(byte value) { + super(value, Constants.TEXTS3[value]); + if (value < 4 || value > 12) { + throw new ClassGenException(("Invalid type: " + value)); + } + } + + public static final BasicType getType(byte value) { + switch (value) { + case 4: + return BOOLEAN; + case 5: + return CHAR; + case 6: + return FLOAT; + case 7: + return DOUBLE; + case 8: + return BYTE; + case 9: + return SHORT; + case 10: + return INT; + case 11: + return LONG; + case 12: + return VOID; + default: + throw new ClassGenException(("Invalid type: " + value)); + } + } + + @Override + public int hashCode() { + return this.type; + } + + @Override + public boolean equals(Object result) { + return result instanceof BasicType ? ((BasicType) result).type == this.type : false; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/BranchHandle.java b/src/main/java/com/allatori/lib/bcel/generic/BranchHandle.java new file mode 100644 index 0000000..f082b8e --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/BranchHandle.java @@ -0,0 +1,69 @@ +package com.allatori.lib.bcel.generic; + +public final class BranchHandle extends InstructionHandle { + + public static BranchHandle bh_list = null; + + public BranchInstruction bi; + + public static final BranchHandle getBranchHandle(BranchInstruction branchInstruction) { + if (bh_list == null) { + return new BranchHandle(branchInstruction); + } + BranchHandle branchHandle = bh_list; + bh_list = (BranchHandle) bh_list.instructionHandle2; + branchHandle.setInstruction(branchInstruction); + return branchHandle; + } + + @Override + public int updatePosition(int value, int value2) { + int value3 = this.bi.updatePosition(value, value2); + this.i_position = this.bi.count; + return value3; + } + + public BranchHandle(BranchInstruction branchInstruction) { + super(branchInstruction); + this.bi = branchInstruction; + } + + public void updateTarget( + InstructionHandle instructionHandle, InstructionHandle instructionHandle2) { + this.bi.updateTarget(instructionHandle, instructionHandle2); + } + + public InstructionHandle getTarget() { + return this.bi.getTarget(); + } + + @Override + public void setPosition(int value) { + this.i_position = this.bi.count = value; + } + + @Override + public void update2() { + this.instructionHandle2 = bh_list; + bh_list = this; + } + + @Override + public void setInstruction(Instruction instruction) { + super.setInstruction(instruction); + if (!(instruction instanceof BranchInstruction)) { + throw new ClassGenException( + ("Assigning " + instruction + " to branch handle which is not a branch instruction")); + } + this.bi = (BranchInstruction) instruction; + } + + @Override + public int getPosition() { + return this.bi.count; + } + + public void setTarget(InstructionHandle instructionHandle) { + this.bi.setTarget(instructionHandle); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/BranchInstruction.java b/src/main/java/com/allatori/lib/bcel/generic/BranchInstruction.java new file mode 100644 index 0000000..c8565bc --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/BranchInstruction.java @@ -0,0 +1,134 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.util.ByteSequence; +import java.io.DataOutputStream; +import java.io.IOException; + +public abstract class BranchInstruction extends Instruction implements InstructionTargeter { + + public InstructionHandle target; + + public int count; + + public int index; + + public int getTargetOffset() { + return this.getTargetOffset(this.target); + } + + @Override + public void updateTarget( + InstructionHandle instructionHandle, InstructionHandle instructionHandle2) { + if (this.target == instructionHandle) { + this.setTarget(instructionHandle2); + } else { + throw new ClassGenException(("Not targeting " + instructionHandle + ", but " + this.target)); + } + } + + public static final void notifyTarget( + InstructionHandle instructionHandle, + InstructionHandle instructionHandle2, + InstructionTargeter instructionTargeter) { + if (instructionHandle != null) { + instructionHandle.removeTargeter(instructionTargeter); + } + if (instructionHandle2 != null) { + instructionHandle2.addTargeter(instructionTargeter); + } + } + + public void setTarget(InstructionHandle instructionHandle) { + notifyTarget(this.target, instructionHandle, this); + this.target = instructionHandle; + } + + public InstructionHandle getTarget() { + return this.target; + } + + @Override + public boolean containsTarget(InstructionHandle instructionHandle) { + return this.target == instructionHandle; + } + + @Override + public void dispose() { + this.setTarget(null); + this.index = -1; + this.count = -1; + } + + public int updatePosition(int count, int value2) { + this.count += count; + return 0; + } + + @Override + public String toString(boolean matches) { + String text = super.toString(matches); + String text2 = "null"; + if (matches) { + if (this.target != null) { + if (this.target.getInstruction() == this) { + text2 = ""; + } else if (this.target.getInstruction() == null) { + text2 = ""; + } else { + text2 = this.target.getInstruction().toString(false); + } + } + } else if (this.target != null) { + this.index = this.getTargetOffset(); + text2 = "" + (this.index + this.count); + } + return "" + text + " -> " + text2; + } + + public int getTargetOffset(InstructionHandle instructionHandle) { + if (instructionHandle == null) { + throw new ClassGenException( + ("Target of " + super.toString(true) + " is invalid null handle")); + } else { + int value; + if ((value = instructionHandle.getPosition()) < 0) { + throw new ClassGenException( + ("Invalid branch target position offset for " + + super.toString(true) + + ":" + + value + + ":" + + instructionHandle)); + } else { + return value - this.count; + } + } + } + + public BranchInstruction() {} + + public BranchInstruction(short value, InstructionHandle instructionHandle) { + super(value, (short) 3); + this.setTarget(instructionHandle); + } + + public final int getIndex() { + return this.index; + } + + @Override + public void initFromFile(ByteSequence byteSequence, boolean matches) throws IOException { + this.length = 3; + this.index = byteSequence.readShort(); + } + + @Override + public void dump(DataOutputStream dataOutputStream) throws IOException { + dataOutputStream.writeByte(this.opcode); + this.index = this.getTargetOffset(); + if (Math.abs(this.index) >= 32767) { + throw new ClassGenException("Branch target offset too large for short"); + } + dataOutputStream.writeShort(this.index); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/CALOAD.java b/src/main/java/com/allatori/lib/bcel/generic/CALOAD.java new file mode 100644 index 0000000..e459e77 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/CALOAD.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class CALOAD extends ArrayInstruction implements StackProducer { + + public CALOAD() { + super((short) 52); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitStackProducer(this); + visitor.visitExceptionThrower(this); + visitor.visitTypedInstruction(this); + visitor.visitArrayInstruction(this); + visitor.visitCALOAD(this); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/CASTORE.java b/src/main/java/com/allatori/lib/bcel/generic/CASTORE.java new file mode 100644 index 0000000..464bfa9 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/CASTORE.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class CASTORE extends ArrayInstruction implements StackConsumer { + + public CASTORE() { + super((short) 85); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitStackConsumer(this); + visitor.visitExceptionThrower(this); + visitor.visitTypedInstruction(this); + visitor.visitArrayInstruction(this); + visitor.visitCASTORE(this); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/CHECKCAST.java b/src/main/java/com/allatori/lib/bcel/generic/CHECKCAST.java new file mode 100644 index 0000000..6345b9f --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/CHECKCAST.java @@ -0,0 +1,41 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.ExceptionConstants; + +public class CHECKCAST extends CPInstruction + implements LoadClass, ExceptionThrower, StackProducer, StackConsumer { + + @Override + public ObjectType getLoadClassType(ConstantPoolGen constantPoolGen) { + Type type; + if ((type = this.getType(constantPoolGen)) instanceof ArrayType) { + type = ((ArrayType) type).getBasicType(); + } + return type instanceof ObjectType ? (ObjectType) type : null; + } + + public CHECKCAST() {} + + @Override + public void accept(Visitor visitor) { + visitor.visitLoadClass(this); + visitor.visitExceptionThrower(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitTypedInstruction(this); + visitor.visitCPInstruction(this); + visitor.visitCHECKCAST(this); + } + + @Override + public Class[] getExceptions() { + Class[] classs = new Class[1 + ExceptionConstants.TYPES5.length]; + System.arraycopy(ExceptionConstants.TYPES5, 0, classs, 0, ExceptionConstants.TYPES5.length); + classs[ExceptionConstants.TYPES5.length] = ExceptionConstants.TYPE; + return classs; + } + + public CHECKCAST(int value) { + super((short) 192, value); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/CPInstruction.java b/src/main/java/com/allatori/lib/bcel/generic/CPInstruction.java new file mode 100644 index 0000000..634ca84 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/CPInstruction.java @@ -0,0 +1,72 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.Constants; +import com.allatori.lib.bcel.classfile.Constant; +import com.allatori.lib.bcel.classfile.ConstantClass; +import com.allatori.lib.bcel.classfile.ConstantPool; +import com.allatori.lib.bcel.util.ByteSequence; +import java.io.DataOutputStream; +import java.io.IOException; + +public abstract class CPInstruction extends Instruction + implements TypedInstruction, IndexedInstruction { + + public int index; + + @Override + public final int getIndex() { + return this.index; + } + + public CPInstruction() {} + + @Override + public String toString(boolean matches) { + return "" + super.toString(matches) + " " + this.index; + } + + @Override + public void setIndex(int index) { + if (index < 0) { + throw new ClassGenException(("Negative index value: " + index)); + } + this.index = index; + } + + @Override + public void dump(DataOutputStream dataOutputStream) throws IOException { + dataOutputStream.writeByte(this.opcode); + dataOutputStream.writeShort(this.index); + } + + public CPInstruction(short value, int value2) { + super(value, (short) 3); + this.setIndex(value2); + } + + @Override + public String toString(ConstantPool constantPool) { + Constant constant; + String text = constantPool.constantToString(constant = constantPool.getConstant(this.index)); + if (constant instanceof ConstantClass) { + text = text.replace('.', '/'); + } + return "" + Constants.TEXTS8[this.opcode] + " " + text; + } + + @Override + public void initFromFile(ByteSequence byteSequence, boolean matches) throws IOException { + this.setIndex(byteSequence.readUnsignedShort()); + this.length = 3; + } + + @Override + public Type getType(ConstantPoolGen constantPoolGen) { + String text; + if (!(text = constantPoolGen.getConstantPool().createText(this.index, (byte) 7)) + .startsWith("[")) { + text = "L" + text + ";"; + } + return Type.getType(text); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/ClassElementValueGen.java b/src/main/java/com/allatori/lib/bcel/generic/ClassElementValueGen.java new file mode 100644 index 0000000..d1819d2 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/ClassElementValueGen.java @@ -0,0 +1,60 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.classfile.ClassElementValue; +import com.allatori.lib.bcel.classfile.ConstantUtf8; +import com.allatori.lib.bcel.classfile.ElementValue; +import java.io.DataOutputStream; +import java.io.IOException; + +public class ClassElementValueGen extends ElementValueGen { + + public int idx; + + @Override + public void dump(DataOutputStream dataOutputStream) throws IOException { + dataOutputStream.writeByte(this.type); + dataOutputStream.writeShort(this.idx); + } + + public ClassElementValueGen(ObjectType objectType, ConstantPoolGen constantPoolGen) { + super(99, constantPoolGen); + this.idx = constantPoolGen.addUtf8(objectType.getSignature()); + } + + public String getIdx() { + return ((ConstantUtf8) this.getConstantPool().getConstant(this.idx)).getBytes(); + } + + @Override + public ElementValue getElementValue() { + return new ClassElementValue(this.type, this.idx, this.cpGen.getConstantPool()); + } + + public void setIdx(int idx) { + this.idx = idx; + } + + public ClassElementValueGen(int idx, ConstantPoolGen constantPoolGen) { + super(99, constantPoolGen); + this.idx = idx; + } + + @Override + public String stringifyValue() { + return this.getIdx(); + } + + public ClassElementValueGen( + ClassElementValue classElementValue, ConstantPoolGen constantPoolGen, boolean matches) { + super(99, constantPoolGen); + if (matches) { + this.idx = constantPoolGen.addUtf8(classElementValue.getText2()); + } else { + this.idx = classElementValue.getIndex(); + } + } + + public int getIndex() { + return this.idx; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/ClassGen.java b/src/main/java/com/allatori/lib/bcel/generic/ClassGen.java new file mode 100644 index 0000000..8f208f7 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/ClassGen.java @@ -0,0 +1,499 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.internal.BytecodeSupport; +import com.allatori.lib.bcel.classfile.AccessFlags; +import com.allatori.lib.bcel.classfile.AnnotationEntry; +import com.allatori.lib.bcel.classfile.Annotations; +import com.allatori.lib.bcel.classfile.Attribute; +import com.allatori.lib.bcel.classfile.ConstantPool; +import com.allatori.lib.bcel.classfile.Field; +import com.allatori.lib.bcel.classfile.JavaClass; +import com.allatori.lib.bcel.classfile.Method; +import com.allatori.lib.bcel.classfile.RuntimeInvisibleAnnotations; +import com.allatori.lib.bcel.classfile.RuntimeVisibleAnnotations; +import com.allatori.lib.bcel.classfile.SourceFile; +import com.allatori.lib.bcel.classfile.Utility; +import com.allatori.lib.bcel.util.BCELComparator; +import com.allatori.lib.bcel.util.comparator.ClassGenComparator; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class ClassGen extends AccessFlags implements Cloneable { + + public int minor; + + public List attributes; + + public static BCELComparator _cmp = new ClassGenComparator(); + + public List annotations; + + public List fields; + + public ArrayList observers; + + public ConstantPoolGen cp; + + public int superclassNameIndex; + + public String superclassName; + + public String className; + + public int major; + + public String fileName; + + public List methods; + + public int classNameIndex = -1; + + public List interfaceNames; + + public ClassGen( + String className, + String superclassName, + String fileName, + int access_flags, + String[] texts, + ConstantPoolGen constantPoolGen) { + super(); + this.classNameIndex = -1; + this.superclassNameIndex = -1; + this.major = 45; + this.minor = 3; + this.fields = new ArrayList(); + this.methods = new ArrayList(); + this.attributes = new ArrayList(); + this.interfaceNames = new ArrayList(); + this.annotations = new ArrayList(); + this.className = className; + this.superclassName = superclassName; + this.fileName = fileName; + this.access_flags = access_flags; + this.cp = constantPoolGen; + if (fileName != null) { + this.processAttribute( + new SourceFile( + constantPoolGen.addUtf8("SourceFile"), + 2, + constantPoolGen.addUtf8(fileName), + constantPoolGen.getConstantPool())); + } + this.classNameIndex = constantPoolGen.addClass(className); + this.superclassNameIndex = constantPoolGen.addClass(superclassName); + int value2; + if (texts != null) { + for (int value3 = value2 = 0; value3 < texts.length; value3 = value2) { + int value4 = value2; + value2++; + this.processText(texts[value4]); + } + } + } + + public int getClassNameIndex() { + return this.classNameIndex; + } + + public ConstantPoolGen getConstantPool() { + return this.cp; + } + + public int getSuperclassNameIndex() { + return this.superclassNameIndex; + } + + public void processAttribute(Attribute attribute) { + this.attributes.add(attribute); + } + + public String getClassName() { + return this.className; + } + + public void setMethods(Method[] methods2) { + int value = 0; + this.methods.clear(); + for (int index = 0; value < methods2.length; value = index) { + int value2 = index; + index++; + this.processMethod2(methods2[value2]); + } + } + + public Method containsMethod(String text, String text2) { + Iterator iterator2 = this.methods.iterator(); + while (iterator2.hasNext()) { + Method method; + if ((method = (Method) iterator2.next()).getText().equals(text) + && method.getText2().equals(text2)) { + return method; + } + } + return null; + } + + public void addAnnotationEntry(AnnotationEntryGen annotationEntryGen) { + this.annotations.add(annotationEntryGen); + } + + public String[] getInterfaceNames() { + String[] texts = new String[this.interfaceNames.size()]; + this.interfaceNames.toArray(texts); + return texts; + } + + public void processCount2(int classNameIndex) { + this.classNameIndex = classNameIndex; + this.className = + this.cp.getConstantPool().createText(classNameIndex, (byte) 7).replace('/', '.'); + } + + @Override + public Object clone() { + try { + return super.clone(); + } catch (CloneNotSupportedException cloneNotSupportedException) { + System.err.println(cloneNotSupportedException); + return null; + } + } + + public void addAnnotationEntry2(AnnotationEntryGen annotationEntryGen) { + this.annotations.remove(annotationEntryGen); + } + + public JavaClass getJavaClass() { + int[] interfaces = this.getInterfaces(); + Field[] fields = this.getFields(); + Method[] methods = this.getMethods(); + Attribute[] attributes2; + ClassGen classGen; + if (this.annotations.size() == 0) { + classGen = this; + attributes2 = this.getAttributes(); + } else { + Attribute[] attributes3 = Utility.createAttributes(this.cp, this.annotations); + attributes2 = new Attribute[this.attributes.size() + attributes3.length]; + this.attributes.toArray(attributes2); + System.arraycopy(attributes3, 0, attributes2, this.attributes.size(), attributes3.length); + classGen = this; + } + ConstantPool finalConstantPool = classGen.cp.getFinalConstantPool(); + return new JavaClass( + this.classNameIndex, + this.superclassNameIndex, + this.fileName, + this.major, + this.minor, + this.access_flags, + finalConstantPool, + interfaces, + fields, + methods, + attributes2); + } + + public void processText(String text) { + this.interfaceNames.add(text); + } + + public void processField(Field field) { + this.fields.add(field); + } + + public String getFileName() { + return this.fileName; + } + + public Field containsField(String text) { + Iterator iterator2 = this.fields.iterator(); + while (iterator2.hasNext()) { + Field field; + if ((field = (Field) iterator2.next()).getText().equals(text)) { + return field; + } + } + return null; + } + + public void processCount3(int superclassNameIndex) { + this.superclassNameIndex = superclassNameIndex; + this.superclassName = + this.cp.getConstantPool().createText(superclassNameIndex, (byte) 7).replace('/', '.'); + } + + public void update() { + Iterator iterator2; + if (this.observers != null) { + for (Iterator iterator3 = iterator2 = this.observers.iterator(); + iterator3.hasNext(); + iterator3 = iterator2) { + ((BytecodeSupport) iterator2.next()).processClassGen(this); + } + } + } + + public void replaceMethod(Method method, Method method2) { + if (method2 == null) { + throw new ClassGenException("Replacement method must not be null"); + } + int value; + if ((value = this.methods.indexOf(method)) < 0) { + this.methods.add(method2); + } else { + this.methods.set(value, method2); + } + } + + public static BCELComparator getComparator() { + return _cmp; + } + + public AnnotationEntryGen[] unpackAnnotations(Attribute[] attributes) { + ArrayList values = new ArrayList(); + int value; + for (int value2 = value = 0; value2 < attributes.length; value2 = ++value) { + Attribute attribute; + if ((attribute = attributes[value]) instanceof RuntimeVisibleAnnotations) { + AnnotationEntry[] annotationEntries = + ((RuntimeVisibleAnnotations) attribute).getAnnotationEntries(); + int value3; + for (int value4 = value3 = 0; value4 < annotationEntries.length; value4 = value3) { + AnnotationEntry annotationEntry = annotationEntries[value3]; + ConstantPoolGen constantPool = this.getConstantPool(); + value3++; + values.add(new AnnotationEntryGen(annotationEntry, constantPool, false)); + } + } else if (attribute instanceof RuntimeInvisibleAnnotations) { + AnnotationEntry[] annotationEntries2 = + ((RuntimeInvisibleAnnotations) attribute).getAnnotationEntries(); + int value5; + for (int value6 = value5 = 0; value6 < annotationEntries2.length; value6 = value5) { + AnnotationEntry annotationEntry2 = annotationEntries2[value5]; + ConstantPoolGen constantPool2 = this.getConstantPool(); + value5++; + values.add(new AnnotationEntryGen(annotationEntry2, constantPool2, false)); + } + } + } + return (AnnotationEntryGen[]) values.toArray(new AnnotationEntryGen[values.size()]); + } + + public void setMethodAt(Method method, int value) { + this.methods.set(value, method); + } + + public Method[] getMethods() { + return (Method[]) this.methods.toArray(new Method[this.methods.size()]); + } + + public Attribute[] getAttributes() { + return (Attribute[]) this.attributes.toArray(new Attribute[this.attributes.size()]); + } + + public void processBytecodeSupport(BytecodeSupport bytecodeSupport) { + if (this.observers == null) { + this.observers = new ArrayList(); + } + this.observers.add(bytecodeSupport); + } + + @Override + public boolean equals(Object result) { + return _cmp.equals(this, result); + } + + public void processText2(String text) { + this.superclassName = text.replace('/', '.'); + this.superclassNameIndex = this.cp.addClass(text); + } + + public Field[] getFields() { + return (Field[]) this.fields.toArray(new Field[this.fields.size()]); + } + + public int[] getInterfaces() { + int value; + int[] values = new int[value = this.interfaceNames.size()]; + int value2; + for (int value3 = value2 = 0; value3 < value; value3 = value2) { + int value4 = this.cp.addClass((String) this.interfaceNames.get(value2)); + int value5 = value2; + value2++; + values[value5] = value4; + } + return values; + } + + public ClassGen(String text, String text2, String text3, int value, String[] texts) { + this(text, text2, text3, value, texts, new ConstantPoolGen()); + } + + public void processField2(Field field) { + this.fields.remove(field); + } + + public int getMajor() { + return this.major; + } + + public Method getMethodAt(int value) { + return (Method) this.methods.get(value); + } + + public AnnotationEntryGen[] getAnnotationEntries() { + return (AnnotationEntryGen[]) + this.annotations.toArray(new AnnotationEntryGen[this.annotations.size()]); + } + + public void processCount4(int value) { + InstructionList instructionList; + (instructionList = new InstructionList()).getInstructionHandle(InstructionConstants.ALOAD_0); + instructionList.getInstructionHandle( + new INVOKESPECIAL(this.cp.addMethodref(this.superclassName, "", "()V"))); + instructionList.getInstructionHandle(InstructionConstants.RETURN); + MethodGen methodGen = + new MethodGen( + value, + Type.VOID, + Type.NO_ARGS, + null, + "", + this.className, + instructionList, + this.cp); + methodGen.setCount2(1); + this.processMethod2(methodGen.getMethod()); + } + + public void processMethod(Method method) { + this.methods.remove(method); + } + + public boolean containsField(Field field) { + return this.fields.contains(field); + } + + public static void setComparator(BCELComparator bCELComparator) { + _cmp = bCELComparator; + } + + public void replaceField(Field field, Field field2) { + if (field2 == null) { + throw new ClassGenException("Replacement method must not be null"); + } + int value; + if ((value = this.fields.indexOf(field)) < 0) { + this.fields.add(field2); + } else { + this.fields.set(value, field2); + } + } + + public ClassGen(JavaClass javaClass) { + this.superclassNameIndex = -1; + this.major = 45; + this.minor = 3; + this.fields = new ArrayList(); + this.methods = new ArrayList(); + this.attributes = new ArrayList(); + this.interfaceNames = new ArrayList(); + this.annotations = new ArrayList(); + this.classNameIndex = javaClass.getCount(); + this.superclassNameIndex = javaClass.getCount2(); + this.className = javaClass.getText2(); + this.superclassName = javaClass.getText5(); + this.fileName = javaClass.getText(); + this.access_flags = javaClass.getAccess_flags2(); + this.cp = new ConstantPoolGen(javaClass.getConstantPool()); + this.major = javaClass.getCount3(); + this.minor = javaClass.getCount4(); + Attribute[] attributes2; + AnnotationEntryGen[] annotationEntryGens = + this.unpackAnnotations(attributes2 = javaClass.getAttributes()); + Method[] methods2 = javaClass.getMethods(); + Field[] fields2 = javaClass.getFields(); + String[] interfaceNames2 = javaClass.getInterfaceNames(); + int value; + for (int value2 = value = 0; value2 < interfaceNames2.length; value2 = value) { + int value3 = value; + value++; + this.processText(interfaceNames2[value3]); + } + int value4; + for (int value5 = value4 = 0; value5 < attributes2.length; value5 = ++value4) { + if (!(attributes2[value4] instanceof Annotations)) { + this.processAttribute(attributes2[value4]); + } + } + int value6; + for (int value7 = value6 = 0; value7 < annotationEntryGens.length; value7 = value6) { + int value8 = value6; + value6++; + this.addAnnotationEntry(annotationEntryGens[value8]); + } + int value9; + for (int value10 = value9 = 0; value10 < methods2.length; value10 = value9) { + int value11 = value9; + value9++; + this.processMethod2(methods2[value11]); + } + int value12; + for (int value13 = value12 = 0; value13 < fields2.length; value13 = value12) { + int value14 = value12; + value12++; + this.processField(fields2[value14]); + } + } + + public String getSuperclassName() { + return this.superclassName; + } + + public void setConstantPool(ConstantPoolGen constantPoolGen) { + this.cp = constantPoolGen; + } + + public void processText3(String text) { + this.interfaceNames.remove(text); + } + + public void setMajor(int major) { + this.major = major; + } + + public void processText4(String text) { + this.className = text.replace('/', '.'); + this.classNameIndex = this.cp.addClass(text); + } + + public void setMinor(int minor) { + this.minor = minor; + } + + public void processMethod2(Method method) { + this.methods.add(method); + } + + @Override + public int hashCode() { + return _cmp.hashCode(this); + } + + public int getMinor() { + return this.minor; + } + + public void processAttribute2(Attribute attribute) { + this.attributes.remove(attribute); + } + + public void processBytecodeSupport2(BytecodeSupport bytecodeSupport) { + if (this.observers != null) { + this.observers.remove(bytecodeSupport); + } + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/ClassGenException.java b/src/main/java/com/allatori/lib/bcel/generic/ClassGenException.java new file mode 100644 index 0000000..f8f8e30 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/ClassGenException.java @@ -0,0 +1,10 @@ +package com.allatori.lib.bcel.generic; + +public class ClassGenException extends RuntimeException { + + public ClassGenException(String text) { + super(text); + } + + public ClassGenException() {} +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/ClassObserver.java b/src/main/java/com/allatori/lib/bcel/generic/ClassObserver.java new file mode 100644 index 0000000..78362f3 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/ClassObserver.java @@ -0,0 +1,6 @@ +package com.allatori.lib.bcel.generic; + +public interface ClassObserver { + + void notify(ClassGen classGen); +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/CodeExceptionGen.java b/src/main/java/com/allatori/lib/bcel/generic/CodeExceptionGen.java new file mode 100644 index 0000000..1ef7f5a --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/CodeExceptionGen.java @@ -0,0 +1,117 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.classfile.CodeException; +import java.io.Serializable; + +public final class CodeExceptionGen implements InstructionTargeter, Cloneable, Serializable { + + public InstructionHandle instructionHandle; + + public ObjectType catch_type; + + public InstructionHandle instructionHandle2; + + public InstructionHandle instructionHandle3; + + public ObjectType getCatchType() { + return this.catch_type; + } + + public void setCatchType(ObjectType objectType) { + this.catch_type = objectType; + } + + public InstructionHandle getInstructionHandle3() { + return this.instructionHandle3; + } + + public InstructionHandle getInstructionHandle() { + return this.instructionHandle; + } + + public CodeException getCodeException(ConstantPoolGen constantPoolGen) { + return new CodeException( + this.instructionHandle2.getPosition(), + this.instructionHandle.getPosition() + this.instructionHandle.getInstruction().getLength(), + this.instructionHandle3.getPosition(), + this.catch_type == null ? 0 : constantPoolGen.addClass(this.catch_type)); + } + + public InstructionHandle getInstructionHandle2() { + return this.instructionHandle2; + } + + public void processInstructionHandle(InstructionHandle instructionHandle2) { + BranchInstruction.notifyTarget(this.instructionHandle, instructionHandle2, this); + this.instructionHandle = instructionHandle2; + } + + @Override + public Object clone() { + try { + return super.clone(); + } catch (CloneNotSupportedException cloneNotSupportedException) { + System.err.println(cloneNotSupportedException); + return null; + } + } + + public void processInstructionHandle2(InstructionHandle instructionHandle) { + BranchInstruction.notifyTarget(this.instructionHandle2, instructionHandle, this); + this.instructionHandle2 = instructionHandle; + } + + public void processInstructionHandle3(InstructionHandle instructionHandle) { + BranchInstruction.notifyTarget(this.instructionHandle3, instructionHandle, this); + this.instructionHandle3 = instructionHandle; + } + + public CodeExceptionGen( + InstructionHandle instructionHandle, + InstructionHandle instructionHandle2, + InstructionHandle instructionHandle3, + ObjectType objectType) { + super(); + this.processInstructionHandle2(instructionHandle); + this.processInstructionHandle(instructionHandle2); + this.processInstructionHandle3(instructionHandle3); + this.catch_type = objectType; + } + + @Override + public boolean containsTarget(InstructionHandle instructionHandle4) { + return this.instructionHandle2 == instructionHandle4 + || this.instructionHandle == instructionHandle4 + || this.instructionHandle3 == instructionHandle4; + } + + @Override + public void updateTarget( + InstructionHandle instructionHandle4, InstructionHandle instructionHandle5) { + byte value = 0; + if (this.instructionHandle2 == instructionHandle4) { + value = 1; + this.processInstructionHandle2(instructionHandle5); + } + if (this.instructionHandle == instructionHandle4) { + value = 1; + this.processInstructionHandle(instructionHandle5); + } + if (this.instructionHandle3 == instructionHandle4) { + value = 1; + this.processInstructionHandle3(instructionHandle5); + } + if (value == 0) { + throw new ClassGenException( + ("Not targeting " + + instructionHandle4 + + ", but {" + + this.instructionHandle2 + + ", " + + this.instructionHandle + + ", " + + this.instructionHandle3 + + "}")); + } + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/CompoundInstruction.java b/src/main/java/com/allatori/lib/bcel/generic/CompoundInstruction.java new file mode 100644 index 0000000..e4a8353 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/CompoundInstruction.java @@ -0,0 +1,6 @@ +package com.allatori.lib.bcel.generic; + +public interface CompoundInstruction { + + InstructionList getInstructionList(); +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/ConstantPoolGen$Index.java b/src/main/java/com/allatori/lib/bcel/generic/ConstantPoolGen$Index.java new file mode 100644 index 0000000..576104a --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/ConstantPoolGen$Index.java @@ -0,0 +1,13 @@ +package com.allatori.lib.bcel.generic; + +import java.io.Serializable; + +public class ConstantPoolGen$Index implements Serializable { + + public int index; + + public ConstantPoolGen$Index(int index) { + super(); + this.index = index; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/ConstantPoolGen.java b/src/main/java/com/allatori/lib/bcel/generic/ConstantPoolGen.java new file mode 100644 index 0000000..572112f --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/ConstantPoolGen.java @@ -0,0 +1,519 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.classfile.Constant; +import com.allatori.lib.bcel.classfile.ConstantCP; +import com.allatori.lib.bcel.classfile.ConstantClass; +import com.allatori.lib.bcel.classfile.ConstantDouble; +import com.allatori.lib.bcel.classfile.ConstantFieldref; +import com.allatori.lib.bcel.classfile.ConstantFloat; +import com.allatori.lib.bcel.classfile.ConstantInteger; +import com.allatori.lib.bcel.classfile.ConstantInterfaceMethodref; +import com.allatori.lib.bcel.classfile.ConstantLong; +import com.allatori.lib.bcel.classfile.ConstantMethodref; +import com.allatori.lib.bcel.classfile.ConstantNameAndType; +import com.allatori.lib.bcel.classfile.ConstantPool; +import com.allatori.lib.bcel.classfile.ConstantString; +import com.allatori.lib.bcel.classfile.ConstantUtf8; +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +public class ConstantPoolGen implements Serializable { + + public Map utf8_table; + + public static final String TEXT = ":"; + + public static final String TEXT4 = "#"; + + public static final String TEXT2 = "&"; + + public static final String TEXT3 = "%"; + + public Map n_a_t_table; + + public int index; + + public Map class_table; + + public Constant[] constants; + + public Map cp_table; + + public Map string_table; + + public int size = 1024; + + public void setConstant(int value, Constant constant) { + this.constants[value] = constant; + } + + public int lookupInteger(int value) { + int value2; + for (int value3 = value2 = 1; value3 < this.index; value3 = ++value2) { + if (this.constants[value2] instanceof ConstantInteger + && ((ConstantInteger) this.constants[value2]).getBytes() == value) { + return value2; + } + } + return -1; + } + + public int lookupUtf8(String text) { + ConstantPoolGen$Index constantPoolGen$Index; + return (constantPoolGen$Index = (ConstantPoolGen$Index) this.utf8_table.get(text)) != null + ? constantPoolGen$Index.index + : -1; + } + + public int addMethodref(String text, String text2, String text3) { + int value; + if ((value = this.calculateCount3(text, text2, text3)) != -1) { + return value; + } + this.adjustSize(); + int value2 = this.addNameAndType(text2, text3); + int value3 = this.addClass(text); + int value4 = this.index; + this.constants[this.index++] = new ConstantMethodref(value3, value2); + String text4 = "" + text + ":" + text2 + ":" + text3; + if (!this.cp_table.containsKey(text4)) { + this.cp_table.put(text4, new ConstantPoolGen$Index(value4)); + } + return value4; + } + + public int addClass_(String text) { + int value; + if ((value = this.lookupClass(text)) != -1) { + return value; + } + this.adjustSize(); + ConstantClass constantClass = new ConstantClass(this.addUtf8(text)); + int value2 = this.index; + this.constants[this.index++] = constantClass; + if (!this.class_table.containsKey(text)) { + this.class_table.put(text, new ConstantPoolGen$Index(value2)); + } + return value2; + } + + public int addInteger(int value) { + int value2; + if ((value2 = this.lookupInteger(value)) != -1) { + return value2; + } + this.adjustSize(); + int value3 = this.index; + this.constants[this.index++] = new ConstantInteger(value); + return value3; + } + + public ConstantPool getFinalConstantPool() { + Constant[] constants2 = new Constant[this.index]; + System.arraycopy(this.constants, 0, constants2, 0, this.index); + return new ConstantPool(constants2); + } + + public int addDouble(double value) { + int value2; + if ((value2 = this.lookupDouble(value)) != -1) { + return value2; + } + this.adjustSize(); + int value3 = this.index; + this.constants[this.index] = new ConstantDouble(value); + this.index += 2; + return value3; + } + + public int addNameAndType(String text, String text2) { + int value; + if ((value = this.lookupNameAndType(text, text2)) != -1) { + return value; + } + this.adjustSize(); + int value2 = this.addUtf8(text); + int value3 = this.addUtf8(text2); + int value4 = this.index; + this.constants[this.index++] = new ConstantNameAndType(value2, value3); + String text3 = "" + text + "%" + text2; + if (!this.n_a_t_table.containsKey(text3)) { + this.n_a_t_table.put(text3, new ConstantPoolGen$Index(value4)); + } + return value4; + } + + public ConstantPoolGen(Constant[] constants2) { + this.constants = new Constant[this.size]; + this.index = 1; + this.string_table = new HashMap(); + this.class_table = new HashMap(); + this.utf8_table = new HashMap(); + this.n_a_t_table = new HashMap(); + this.cp_table = new HashMap(); + if (constants2.length > this.size) { + this.size = constants2.length; + this.constants = new Constant[this.size]; + } + System.arraycopy(constants2, 0, this.constants, 0, constants2.length); + if (constants2.length > 0) { + this.index = constants2.length; + } + int value; + for (int value2 = value = 1; value2 < this.index; value2 = ++value) { + Constant constant; + if ((constant = this.constants[value]) instanceof ConstantString) { + ConstantString constantString = (ConstantString) constant; + String bytes = ((ConstantUtf8) this.constants[constantString.getStringIndex()]).getBytes(); + if (!this.string_table.containsKey(bytes)) { + this.string_table.put(bytes, new ConstantPoolGen$Index(value)); + } + } else if (constant instanceof ConstantClass) { + ConstantClass constantClass = (ConstantClass) constant; + String bytes2 = ((ConstantUtf8) this.constants[constantClass.getNameIndex()]).getBytes(); + if (!this.class_table.containsKey(bytes2)) { + this.class_table.put(bytes2, new ConstantPoolGen$Index(value)); + } + } else if (constant instanceof ConstantNameAndType) { + ConstantNameAndType constantNameAndType = (ConstantNameAndType) constant; + ConstantUtf8 constantUtf8 = + (ConstantUtf8) this.constants[constantNameAndType.getName_index()]; + ConstantUtf8 constantUtf82 = + (ConstantUtf8) this.constants[constantNameAndType.getSignature_index()]; + String text = "" + constantUtf8.getBytes() + "%" + constantUtf82.getBytes(); + if (!this.n_a_t_table.containsKey(text)) { + this.n_a_t_table.put(text, new ConstantPoolGen$Index(value)); + } + } else if (constant instanceof ConstantUtf8) { + String bytes3 = ((ConstantUtf8) constant).getBytes(); + if (!this.utf8_table.containsKey(bytes3)) { + this.utf8_table.put(bytes3, new ConstantPoolGen$Index(value)); + } + } else if (constant instanceof ConstantCP) { + ConstantCP constantCP = (ConstantCP) constant; + ConstantClass constantClass2 = (ConstantClass) this.constants[constantCP.getClass_index()]; + ConstantNameAndType constantNameAndType2 = + (ConstantNameAndType) this.constants[constantCP.getName_and_type_index()]; + String text2 = + ((ConstantUtf8) this.constants[constantClass2.getNameIndex()]) + .getBytes() + .replace('/', '.'); + String bytes4 = + ((ConstantUtf8) this.constants[constantNameAndType2.getName_index()]).getBytes(); + String bytes5 = + ((ConstantUtf8) this.constants[constantNameAndType2.getSignature_index()]).getBytes(); + String text3 = ":"; + if (constant instanceof ConstantInterfaceMethodref) { + text3 = "#"; + } else if (constant instanceof ConstantFieldref) { + text3 = "&"; + } + String text4 = "" + text2 + text3 + bytes4 + text3 + bytes5; + if (!this.cp_table.containsKey(text4)) { + this.cp_table.put(text4, new ConstantPoolGen$Index(value)); + } + } + } + } + + public int lookupDouble(double value) { + long value2 = Double.doubleToLongBits(value); + int value3; + for (int value4 = value3 = 1; value4 < this.index; value4 = ++value3) { + if (this.constants[value3] instanceof ConstantDouble + && Double.doubleToLongBits(((ConstantDouble) this.constants[value3]).getBytes()) + == value2) { + return value3; + } + } + return -1; + } + + public int calculateCount(MethodGen methodGen) { + return this.calculateCount3( + methodGen.getClass_name(), methodGen.getName(), methodGen.getText()); + } + + public int lookupClass(String text) { + ConstantPoolGen$Index constantPoolGen$Index; + return (constantPoolGen$Index = + (ConstantPoolGen$Index) this.class_table.get(text.replace((char) 46, (char) 47))) + != null + ? constantPoolGen$Index.index + : -1; + } + + public ConstantPool getConstantPool() { + return new ConstantPool(this.constants); + } + + public int addArrayClass(ArrayType arrayType) { + return this.addClass_(arrayType.getSignature()); + } + + public int addInterfaceMethodref(String text, String text2, String text3) { + int value; + if ((value = this.calculateCount2(text, text2, text3)) != -1) { + return value; + } + this.adjustSize(); + int value2 = this.addClass(text); + int value3 = this.addNameAndType(text2, text3); + int value4 = this.index; + this.constants[this.index++] = new ConstantInterfaceMethodref(value2, value3); + String text4 = "" + text + "#" + text2 + "#" + text3; + if (!this.cp_table.containsKey(text4)) { + this.cp_table.put(text4, new ConstantPoolGen$Index(value4)); + } + return value4; + } + + public int lookupLong(long value) { + int value2; + for (int value3 = value2 = 1; value3 < this.index; value3 = ++value2) { + if (this.constants[value2] instanceof ConstantLong + && ((ConstantLong) this.constants[value2]).getBytes() == value) { + return value2; + } + } + return -1; + } + + public int lookupString(String text) { + ConstantPoolGen$Index constantPoolGen$Index; + return (constantPoolGen$Index = (ConstantPoolGen$Index) this.string_table.get(text)) != null + ? constantPoolGen$Index.index + : -1; + } + + public Constant getConstant(int value) { + return this.constants[value]; + } + + public int lookupNameAndType(String text, String text2) { + ConstantPoolGen$Index constantPoolGen$Index; + return (constantPoolGen$Index = + (ConstantPoolGen$Index) this.n_a_t_table.get("" + text + "%" + text2)) + != null + ? constantPoolGen$Index.index + : -1; + } + + public int calculateCount2(MethodGen methodGen) { + return this.addMethodref(methodGen.getClass_name(), methodGen.getName(), methodGen.getText()); + } + + public int calculateCount3(MethodGen methodGen) { + return this.addInterfaceMethodref( + methodGen.getClass_name(), methodGen.getName(), methodGen.getText()); + } + + public int addLong(long value) { + int value2; + if ((value2 = this.lookupLong(value)) != -1) { + return value2; + } + this.adjustSize(); + int value3 = this.index; + this.constants[this.index] = new ConstantLong(value); + this.index += 2; + return value3; + } + + public ConstantPoolGen() { + this.constants = new Constant[this.size]; + this.index = 1; + this.string_table = new HashMap(); + this.class_table = new HashMap(); + this.utf8_table = new HashMap(); + this.n_a_t_table = new HashMap(); + this.cp_table = new HashMap(); + } + + public void adjustSize() { + if (this.index + 3 >= this.size) { + Constant[] constants2 = this.constants; + this.size *= 2; + this.constants = new Constant[this.size]; + System.arraycopy(constants2, 0, this.constants, 0, this.index); + } + } + + public int addFieldref(String text, String text2, String text3) { + int value; + if ((value = this.calculateCount(text, text2, text3)) != -1) { + return value; + } + this.adjustSize(); + int value2 = this.addClass(text); + int value3 = this.addNameAndType(text2, text3); + int value4 = this.index; + this.constants[this.index++] = new ConstantFieldref(value2, value3); + String text4 = "" + text + "&" + text2 + "&" + text3; + if (!this.cp_table.containsKey(text4)) { + this.cp_table.put(text4, new ConstantPoolGen$Index(value4)); + } + return value4; + } + + public int calculateCount(String text, String text2, String text3) { + ConstantPoolGen$Index constantPoolGen$Index; + return (constantPoolGen$Index = + (ConstantPoolGen$Index) this.cp_table.get("" + text + "&" + text2 + "&" + text3)) + != null + ? constantPoolGen$Index.index + : -1; + } + + public int addString(String text) { + int value; + if ((value = this.lookupString(text)) != -1) { + return value; + } + int value2 = this.addUtf8(text); + this.adjustSize(); + ConstantString constantString = new ConstantString(value2); + int value3 = this.index; + this.constants[this.index++] = constantString; + if (!this.string_table.containsKey(text)) { + this.string_table.put(text, new ConstantPoolGen$Index(value3)); + } + return value3; + } + + public ConstantPoolGen(ConstantPool constantPool) { + this(constantPool.getConstantPool()); + } + + public int lookupFloat(float value) { + int value2 = Float.floatToIntBits(value); + int value3; + for (int value4 = value3 = 1; value4 < this.index; value4 = ++value3) { + if (this.constants[value3] instanceof ConstantFloat + && Float.floatToIntBits(((ConstantFloat) this.constants[value3]).getBytes()) == value2) { + return value3; + } + } + return -1; + } + + public int addFloat(float value) { + int value2; + if ((value2 = this.lookupFloat(value)) != -1) { + return value2; + } + this.adjustSize(); + int value3 = this.index; + this.constants[this.index++] = new ConstantFloat(value); + return value3; + } + + public int addClass(ObjectType objectType) { + return this.addClass(objectType.getClassName()); + } + + public int calculateCount4(MethodGen methodGen) { + return this.calculateCount2( + methodGen.getClass_name(), methodGen.getName(), methodGen.getText()); + } + + public int calculateCount2(String text, String text2, String text3) { + ConstantPoolGen$Index constantPoolGen$Index; + return (constantPoolGen$Index = + (ConstantPoolGen$Index) this.cp_table.get("" + text + "#" + text2 + "#" + text3)) + != null + ? constantPoolGen$Index.index + : -1; + } + + public int addConstant(Constant constant, ConstantPoolGen constantPoolGen) { + Constant[] constantPool = constantPoolGen.getConstantPool().getConstantPool(); + switch (constant.getTag()) { + case 1: + return this.addUtf8(((ConstantUtf8) constant).getBytes()); + case 2: + default: + throw new RuntimeException(("Unknown constant type " + constant)); + case 3: + return this.addInteger(((ConstantInteger) constant).getBytes()); + case 4: + return this.addFloat(((ConstantFloat) constant).getBytes()); + case 5: + return this.addLong(((ConstantLong) constant).getBytes()); + case 6: + return this.addDouble(((ConstantDouble) constant).getBytes()); + case 7: + ConstantClass constantClass = (ConstantClass) constant; + ConstantUtf8 constantUtf8 = (ConstantUtf8) constantPool[constantClass.getNameIndex()]; + return this.addClass(constantUtf8.getBytes()); + case 8: + ConstantString constantString = (ConstantString) constant; + ConstantUtf8 constantUtf82 = (ConstantUtf8) constantPool[constantString.getStringIndex()]; + return this.addString(constantUtf82.getBytes()); + case 9: + case 10: + case 11: + ConstantCP constantCP = (ConstantCP) constant; + ConstantClass constantClass2 = (ConstantClass) constantPool[constantCP.getClass_index()]; + ConstantNameAndType constantNameAndType = + (ConstantNameAndType) constantPool[constantCP.getName_and_type_index()]; + String text = + ((ConstantUtf8) constantPool[constantClass2.getNameIndex()]) + .getBytes() + .replace('/', '.'); + String bytes = + ((ConstantUtf8) constantPool[constantNameAndType.getName_index()]).getBytes(); + String bytes2 = + ((ConstantUtf8) constantPool[constantNameAndType.getSignature_index()]).getBytes(); + switch (constant.getTag()) { + case 9: + return this.addFieldref(text, bytes, bytes2); + case 10: + return this.addMethodref(text, bytes, bytes2); + case 11: + return this.addInterfaceMethodref(text, bytes, bytes2); + default: + throw new RuntimeException(("Unknown constant type " + constant)); + } + case 12: + ConstantNameAndType constantNameAndType2 = (ConstantNameAndType) constant; + ConstantUtf8 constantUtf83 = + (ConstantUtf8) constantPool[constantNameAndType2.getName_index()]; + ConstantUtf8 constantUtf84 = + (ConstantUtf8) constantPool[constantNameAndType2.getSignature_index()]; + return this.addNameAndType(constantUtf83.getBytes(), constantUtf84.getBytes()); + } + } + + public int getSize() { + return this.index; + } + + public int calculateCount3(String text, String text2, String text3) { + ConstantPoolGen$Index constantPoolGen$Index; + return (constantPoolGen$Index = + (ConstantPoolGen$Index) this.cp_table.get("" + text + ":" + text2 + ":" + text3)) + != null + ? constantPoolGen$Index.index + : -1; + } + + public int addClass(String text) { + return this.addClass_(text.replace((char) 46, (char) 47)); + } + + public int addUtf8(String text) { + int value; + if ((value = this.lookupUtf8(text)) != -1) { + return value; + } + this.adjustSize(); + int value2 = this.index; + this.constants[this.index++] = new ConstantUtf8(text); + if (!this.utf8_table.containsKey(text)) { + this.utf8_table.put(text, new ConstantPoolGen$Index(value2)); + } + return value2; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/ConstantPushInstruction.java b/src/main/java/com/allatori/lib/bcel/generic/ConstantPushInstruction.java new file mode 100644 index 0000000..359236e --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/ConstantPushInstruction.java @@ -0,0 +1,6 @@ +package com.allatori.lib.bcel.generic; + +public interface ConstantPushInstruction extends PushInstruction, TypedInstruction { + + Number getValue(); +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/ConversionInstruction.java b/src/main/java/com/allatori/lib/bcel/generic/ConversionInstruction.java new file mode 100644 index 0000000..208e661 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/ConversionInstruction.java @@ -0,0 +1,41 @@ +package com.allatori.lib.bcel.generic; + +public abstract class ConversionInstruction extends Instruction + implements TypedInstruction, StackProducer, StackConsumer { + + public ConversionInstruction(short value) { + super(value, (short) 1); + } + + public ConversionInstruction() {} + + @Override + public Type getType(ConstantPoolGen constantPoolGen) { + switch (this.opcode) { + case 133: + case 140: + case 143: + return Type.LONG; + case 134: + case 137: + case 144: + return Type.FLOAT; + case 135: + case 138: + case 141: + return Type.DOUBLE; + case 136: + case 139: + case 142: + return Type.INT; + case 145: + return Type.BYTE; + case 146: + return Type.CHAR; + case 147: + return Type.SHORT; + default: + throw new ClassGenException(("Unknown type " + this.opcode)); + } + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/D2F.java b/src/main/java/com/allatori/lib/bcel/generic/D2F.java new file mode 100644 index 0000000..2dee38a --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/D2F.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class D2F extends ConversionInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitConversionInstruction(this); + visitor.visitD2F(this); + } + + public D2F() { + super((short) 144); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/D2I.java b/src/main/java/com/allatori/lib/bcel/generic/D2I.java new file mode 100644 index 0000000..ec9a0e0 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/D2I.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class D2I extends ConversionInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitConversionInstruction(this); + visitor.visitD2I(this); + } + + public D2I() { + super((short) 142); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/D2L.java b/src/main/java/com/allatori/lib/bcel/generic/D2L.java new file mode 100644 index 0000000..bdf1e2d --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/D2L.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class D2L extends ConversionInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitConversionInstruction(this); + visitor.visitD2L(this); + } + + public D2L() { + super((short) 143); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/DADD.java b/src/main/java/com/allatori/lib/bcel/generic/DADD.java new file mode 100644 index 0000000..ea42e76 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/DADD.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class DADD extends ArithmeticInstruction { + + public DADD() { + super((short) 99); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitArithmeticInstruction(this); + visitor.visitDADD(this); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/DALOAD.java b/src/main/java/com/allatori/lib/bcel/generic/DALOAD.java new file mode 100644 index 0000000..c6f2bc6 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/DALOAD.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class DALOAD extends ArrayInstruction implements StackProducer { + + @Override + public void accept(Visitor visitor) { + visitor.visitStackProducer(this); + visitor.visitExceptionThrower(this); + visitor.visitTypedInstruction(this); + visitor.visitArrayInstruction(this); + visitor.visitDALOAD(this); + } + + public DALOAD() { + super((short) 49); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/DASTORE.java b/src/main/java/com/allatori/lib/bcel/generic/DASTORE.java new file mode 100644 index 0000000..889b43a --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/DASTORE.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class DASTORE extends ArrayInstruction implements StackConsumer { + + @Override + public void accept(Visitor visitor) { + visitor.visitStackConsumer(this); + visitor.visitExceptionThrower(this); + visitor.visitTypedInstruction(this); + visitor.visitArrayInstruction(this); + visitor.visitDASTORE(this); + } + + public DASTORE() { + super((short) 82); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/DCMPG.java b/src/main/java/com/allatori/lib/bcel/generic/DCMPG.java new file mode 100644 index 0000000..507ccef --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/DCMPG.java @@ -0,0 +1,21 @@ +package com.allatori.lib.bcel.generic; + +public class DCMPG extends Instruction implements TypedInstruction, StackProducer, StackConsumer { + + @Override + public Type getType(ConstantPoolGen constantPoolGen) { + return Type.DOUBLE; + } + + public DCMPG() { + super((short) 152, (short) 1); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitDCMPG(this); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/DCMPL.java b/src/main/java/com/allatori/lib/bcel/generic/DCMPL.java new file mode 100644 index 0000000..fac4880 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/DCMPL.java @@ -0,0 +1,21 @@ +package com.allatori.lib.bcel.generic; + +public class DCMPL extends Instruction implements TypedInstruction, StackProducer, StackConsumer { + + public DCMPL() { + super((short) 151, (short) 1); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitDCMPL(this); + } + + @Override + public Type getType(ConstantPoolGen constantPoolGen) { + return Type.DOUBLE; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/DCONST.java b/src/main/java/com/allatori/lib/bcel/generic/DCONST.java new file mode 100644 index 0000000..57765d0 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/DCONST.java @@ -0,0 +1,43 @@ +package com.allatori.lib.bcel.generic; + +public class DCONST extends Instruction implements ConstantPushInstruction, TypedInstruction { + + public double value; + + public DCONST(double value2) { + super((short) 14, (short) 1); + DCONST dCONST; + if (value2 == 0.0) { + dCONST = this; + this.opcode = 14; + } else { + if (value2 != 1.0) { + throw new ClassGenException(("DCONST can be used only for 0.0 and 1.0: " + value2)); + } + dCONST = this; + this.opcode = 15; + } + dCONST.value = value2; + } + + @Override + public void accept(Visitor visitor) { + visitor.visitPushInstruction(this); + visitor.visitStackProducer(this); + visitor.visitTypedInstruction(this); + visitor.visitConstantPushInstruction(this); + visitor.visitDCONST(this); + } + + @Override + public Type getType(ConstantPoolGen constantPoolGen) { + return Type.DOUBLE; + } + + @Override + public Number getValue() { + return new Double(this.value); + } + + public DCONST() {} +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/DDIV.java b/src/main/java/com/allatori/lib/bcel/generic/DDIV.java new file mode 100644 index 0000000..f3fdd06 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/DDIV.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class DDIV extends ArithmeticInstruction { + + public DDIV() { + super((short) 111); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitArithmeticInstruction(this); + visitor.visitDDIV(this); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/DLOAD.java b/src/main/java/com/allatori/lib/bcel/generic/DLOAD.java new file mode 100644 index 0000000..27cd9a3 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/DLOAD.java @@ -0,0 +1,18 @@ +package com.allatori.lib.bcel.generic; + +public class DLOAD extends LoadInstruction { + + @Override + public void accept(Visitor visitor) { + super.accept(visitor); + visitor.visitDLOAD(this); + } + + public DLOAD() { + super((short) 24, (short) 38); + } + + public DLOAD(int value) { + super((short) 24, (short) 38, value); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/DMUL.java b/src/main/java/com/allatori/lib/bcel/generic/DMUL.java new file mode 100644 index 0000000..ffba578 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/DMUL.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class DMUL extends ArithmeticInstruction { + + public DMUL() { + super((short) 107); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitArithmeticInstruction(this); + visitor.visitDMUL(this); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/DNEG.java b/src/main/java/com/allatori/lib/bcel/generic/DNEG.java new file mode 100644 index 0000000..72bc3f9 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/DNEG.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class DNEG extends ArithmeticInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitArithmeticInstruction(this); + visitor.visitDNEG(this); + } + + public DNEG() { + super((short) 119); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/DREM.java b/src/main/java/com/allatori/lib/bcel/generic/DREM.java new file mode 100644 index 0000000..3d83103 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/DREM.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class DREM extends ArithmeticInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitArithmeticInstruction(this); + visitor.visitDREM(this); + } + + public DREM() { + super((short) 115); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/DRETURN.java b/src/main/java/com/allatori/lib/bcel/generic/DRETURN.java new file mode 100644 index 0000000..7a3d268 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/DRETURN.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class DRETURN extends ReturnInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitExceptionThrower(this); + visitor.visitTypedInstruction(this); + visitor.visitStackConsumer(this); + visitor.visitReturnInstruction(this); + visitor.visitDRETURN(this); + } + + public DRETURN() { + super((short) 175); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/DSTORE.java b/src/main/java/com/allatori/lib/bcel/generic/DSTORE.java new file mode 100644 index 0000000..c20e07f --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/DSTORE.java @@ -0,0 +1,18 @@ +package com.allatori.lib.bcel.generic; + +public class DSTORE extends StoreInstruction { + + public DSTORE() { + super((short) 57, (short) 71); + } + + public DSTORE(int value) { + super((short) 57, (short) 71, value); + } + + @Override + public void accept(Visitor visitor) { + super.accept(visitor); + visitor.visitDSTORE(this); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/DSUB.java b/src/main/java/com/allatori/lib/bcel/generic/DSUB.java new file mode 100644 index 0000000..20f19d3 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/DSUB.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class DSUB extends ArithmeticInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitArithmeticInstruction(this); + visitor.visitDSUB(this); + } + + public DSUB() { + super((short) 103); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/DUP.java b/src/main/java/com/allatori/lib/bcel/generic/DUP.java new file mode 100644 index 0000000..5de3dd3 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/DUP.java @@ -0,0 +1,16 @@ +package com.allatori.lib.bcel.generic; + +public class DUP extends StackInstruction implements PushInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitStackProducer(this); + visitor.visitPushInstruction(this); + visitor.visitStackInstruction(this); + visitor.visitDUP(this); + } + + public DUP() { + super((short) 89); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/DUP2.java b/src/main/java/com/allatori/lib/bcel/generic/DUP2.java new file mode 100644 index 0000000..6fdcd46 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/DUP2.java @@ -0,0 +1,16 @@ +package com.allatori.lib.bcel.generic; + +public class DUP2 extends StackInstruction implements PushInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitStackProducer(this); + visitor.visitPushInstruction(this); + visitor.visitStackInstruction(this); + visitor.visitDUP2(this); + } + + public DUP2() { + super((short) 92); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/DUP2_X1.java b/src/main/java/com/allatori/lib/bcel/generic/DUP2_X1.java new file mode 100644 index 0000000..7e62876 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/DUP2_X1.java @@ -0,0 +1,14 @@ +package com.allatori.lib.bcel.generic; + +public class DUP2_X1 extends StackInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitStackInstruction(this); + visitor.visitDUP2_X1(this); + } + + public DUP2_X1() { + super((short) 93); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/DUP2_X2.java b/src/main/java/com/allatori/lib/bcel/generic/DUP2_X2.java new file mode 100644 index 0000000..bf8e6e7 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/DUP2_X2.java @@ -0,0 +1,14 @@ +package com.allatori.lib.bcel.generic; + +public class DUP2_X2 extends StackInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitStackInstruction(this); + visitor.visitDUP2_X2(this); + } + + public DUP2_X2() { + super((short) 94); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/DUP_X1.java b/src/main/java/com/allatori/lib/bcel/generic/DUP_X1.java new file mode 100644 index 0000000..24904c8 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/DUP_X1.java @@ -0,0 +1,14 @@ +package com.allatori.lib.bcel.generic; + +public class DUP_X1 extends StackInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitStackInstruction(this); + visitor.visitDUP_X1(this); + } + + public DUP_X1() { + super((short) 90); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/DUP_X2.java b/src/main/java/com/allatori/lib/bcel/generic/DUP_X2.java new file mode 100644 index 0000000..52c3b17 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/DUP_X2.java @@ -0,0 +1,14 @@ +package com.allatori.lib.bcel.generic; + +public class DUP_X2 extends StackInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitStackInstruction(this); + visitor.visitDUP_X2(this); + } + + public DUP_X2() { + super((short) 91); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/ElementValueGen.java b/src/main/java/com/allatori/lib/bcel/generic/ElementValueGen.java new file mode 100644 index 0000000..1758209 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/ElementValueGen.java @@ -0,0 +1,227 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.classfile.AnnotationElementValue; +import com.allatori.lib.bcel.classfile.AnnotationEntry; +import com.allatori.lib.bcel.classfile.ArrayElementValue; +import com.allatori.lib.bcel.classfile.ClassElementValue; +import com.allatori.lib.bcel.classfile.ElementValue; +import com.allatori.lib.bcel.classfile.EnumElementValue; +import com.allatori.lib.bcel.classfile.SimpleElementValue; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public abstract class ElementValueGen { + + public static final int ANNOTATION = 64; + + public static final int PRIMITIVE_SHORT = 83; + + public static final int ARRAY = 91; + + public static final int PRIMITIVE_BOOLEAN = 90; + + public static final int PRIMITIVE_FLOAT = 70; + + public static final int PRIMITIVE_DOUBLE = 68; + + public ConstantPoolGen cpGen; + + public static final int ENUM_CONSTANT = 101; + + public static final int PRIMITIVE_CHAR = 67; + + public static final int STRING = 115; + + public int type; + + public static final int PRIMITIVE_INT = 73; + + public static final int PRIMITIVE_LONG = 74; + + public static final int CLASS = 99; + + public static final int PRIMITIVE_BYTE = 66; + + public abstract ElementValue getElementValue(); + + public ElementValueGen(int type, ConstantPoolGen constantPoolGen) { + super(); + this.type = type; + this.cpGen = constantPoolGen; + } + + public int getElementValueType() { + return this.type; + } + + public ConstantPoolGen getConstantPool() { + return this.cpGen; + } + + public static ElementValueGen createElementValueGen( + DataInputStream dataInputStream, ConstantPoolGen constantPoolGen) throws IOException { + int value; + switch (value = dataInputStream.readUnsignedByte()) { + case 64: + return new AnnotationElementValueGen( + 64, + new AnnotationEntryGen( + AnnotationEntry.createAnnotationEntry( + dataInputStream, constantPoolGen.getConstantPool(), true), + constantPoolGen, + false), + constantPoolGen); + case 65: + case 69: + case 71: + case 72: + case 75: + case 76: + case 77: + case 78: + case 79: + case 80: + case 81: + case 82: + case 84: + case 85: + case 86: + case 87: + case 88: + case 89: + case 92: + case 93: + case 94: + case 95: + case 96: + case 97: + case 98: + case 100: + case 102: + case 103: + case 104: + case 105: + case 106: + case 107: + case 108: + case 109: + case 110: + case 111: + case 112: + case 113: + case 114: + default: + throw new RuntimeException(("Unexpected element value kind in annotation: " + value)); + case 66: + return new SimpleElementValueGen(66, dataInputStream.readUnsignedShort(), constantPoolGen); + case 67: + return new SimpleElementValueGen(67, dataInputStream.readUnsignedShort(), constantPoolGen); + case 68: + return new SimpleElementValueGen(68, dataInputStream.readUnsignedShort(), constantPoolGen); + case 70: + return new SimpleElementValueGen(70, dataInputStream.readUnsignedShort(), constantPoolGen); + case 73: + return new SimpleElementValueGen(73, dataInputStream.readUnsignedShort(), constantPoolGen); + case 74: + return new SimpleElementValueGen(74, dataInputStream.readUnsignedShort(), constantPoolGen); + case 83: + return new SimpleElementValueGen(83, dataInputStream.readUnsignedShort(), constantPoolGen); + case 90: + return new SimpleElementValueGen(90, dataInputStream.readUnsignedShort(), constantPoolGen); + case 91: + int value2; + ElementValue[] elementValues = + new ElementValue[value2 = dataInputStream.readUnsignedShort()]; + int value3; + for (int value4 = value3 = 0; value4 < value2; value4 = value3) { + ElementValue elementValue = + ElementValue.createElementValue(dataInputStream, constantPoolGen.getConstantPool()); + int value5 = value3; + value3++; + elementValues[value5] = elementValue; + } + return new ArrayElementValueGen(91, elementValues, constantPoolGen); + case 99: + return new ClassElementValueGen(dataInputStream.readUnsignedShort(), constantPoolGen); + case 101: + return new EnumElementValueGen( + dataInputStream.readUnsignedShort(), + dataInputStream.readUnsignedShort(), + constantPoolGen); + case 115: + return new SimpleElementValueGen(115, dataInputStream.readUnsignedShort(), constantPoolGen); + } + } + + public static ElementValueGen copy( + ElementValue elementValue, ConstantPoolGen constantPoolGen, boolean matches) { + switch (elementValue.getType()) { + case 64: + return new AnnotationElementValueGen( + (AnnotationElementValue) elementValue, constantPoolGen, matches); + case 65: + case 69: + case 71: + case 72: + case 75: + case 76: + case 77: + case 78: + case 79: + case 80: + case 81: + case 82: + case 84: + case 85: + case 86: + case 87: + case 88: + case 89: + case 92: + case 93: + case 94: + case 95: + case 96: + case 97: + case 98: + case 100: + case 102: + case 103: + case 104: + case 105: + case 106: + case 107: + case 108: + case 109: + case 110: + case 111: + case 112: + case 113: + case 114: + default: + throw new RuntimeException(("Not implemented yet! (" + elementValue.getType() + ")")); + case 66: + case 67: + case 68: + case 70: + case 73: + case 74: + case 83: + case 90: + case 115: + return new SimpleElementValueGen( + (SimpleElementValue) elementValue, constantPoolGen, matches); + case 91: + return new ArrayElementValueGen((ArrayElementValue) elementValue, constantPoolGen, matches); + case 99: + return new ClassElementValueGen((ClassElementValue) elementValue, constantPoolGen, matches); + case 101: + return new EnumElementValueGen((EnumElementValue) elementValue, constantPoolGen, matches); + } + } + + public abstract void dump(DataOutputStream dataOutputStream) throws IOException; + + public abstract String stringifyValue(); +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/ElementValuePairGen.java b/src/main/java/com/allatori/lib/bcel/generic/ElementValuePairGen.java new file mode 100644 index 0000000..19081b6 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/ElementValuePairGen.java @@ -0,0 +1,74 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.classfile.ConstantUtf8; +import com.allatori.lib.bcel.classfile.ElementValue; +import com.allatori.lib.bcel.classfile.ElementValuePair; +import java.io.DataOutputStream; +import java.io.IOException; + +public class ElementValuePairGen { + + public ConstantPoolGen cpool; + + public ElementValueGen value; + + public int nameIdx; + + public final String getText() { + return ((ConstantUtf8) this.cpool.getConstant(this.nameIdx)).getBytes(); + } + + public void dump(DataOutputStream dataOutputStream) throws IOException { + dataOutputStream.writeShort(this.nameIdx); + this.value.dump(dataOutputStream); + } + + public int getNameIndex() { + return this.nameIdx; + } + + public void setNameIdx(int nameIdx) { + this.nameIdx = nameIdx; + } + + public ElementValuePairGen( + String text, ElementValueGen elementValueGen, ConstantPoolGen constantPoolGen) { + super(); + this.nameIdx = constantPoolGen.addUtf8(text); + this.value = elementValueGen; + this.cpool = constantPoolGen; + } + + public ElementValuePair getElementNameValuePair() { + ElementValue elementValue = this.value.getElementValue(); + return new ElementValuePair(this.nameIdx, elementValue, this.cpool.getConstantPool()); + } + + public final ElementValueGen getValue() { + return this.value; + } + + public ElementValuePairGen( + ElementValuePair elementValuePair, ConstantPoolGen constantPoolGen, boolean matches) { + super(); + this.cpool = constantPoolGen; + ElementValuePairGen elementValuePairGen; + if (matches) { + elementValuePairGen = this; + this.nameIdx = constantPoolGen.addUtf8(elementValuePair.getText()); + } else { + elementValuePairGen = this; + this.nameIdx = elementValuePair.getNameIndex(); + } + elementValuePairGen.value = + ElementValueGen.copy(elementValuePair.getValue(), constantPoolGen, matches); + } + + public ElementValuePairGen( + int nameIdx, ElementValueGen elementValueGen, ConstantPoolGen constantPoolGen) { + super(); + this.nameIdx = nameIdx; + this.value = elementValueGen; + this.cpool = constantPoolGen; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/EmptyVisitor.java b/src/main/java/com/allatori/lib/bcel/generic/EmptyVisitor.java new file mode 100644 index 0000000..356ad82 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/EmptyVisitor.java @@ -0,0 +1,544 @@ +package com.allatori.lib.bcel.generic; + +public abstract class EmptyVisitor implements Visitor { + + @Override + public void visitACONST_NULL(ACONST_NULL aCONST_NULL) {} + + @Override + public void visitNEW(NEW nEW) {} + + @Override + public void visitFieldOrMethod(FieldOrMethod fieldOrMethod) {} + + @Override + public void visitICONST(ICONST cONST) {} + + @Override + public void visitDCMPG(DCMPG dCMPG) {} + + @Override + public void visitLSTORE(LSTORE lSTORE) {} + + @Override + public void visitLSHR(LSHR lSHR) {} + + @Override + public void visitLALOAD(LALOAD lALOAD) {} + + @Override + public void visitStoreInstruction(StoreInstruction storeInstruction) {} + + @Override + public void visitArithmeticInstruction(ArithmeticInstruction arithmeticInstruction) {} + + @Override + public void visitIF_ICMPEQ(IF_ICMPEQ f_ICMPEQ) {} + + @Override + public void visitINVOKEVIRTUAL(INVOKEVIRTUAL nVOKEVIRTUAL) {} + + @Override + public void visitLocalVariableInstruction(LocalVariableInstruction localVariableInstruction) {} + + @Override + public void visitLRETURN(LRETURN lRETURN) {} + + @Override + public void visitARRAYLENGTH(ARRAYLENGTH aRRAYLENGTH) {} + + @Override + public void visitDRETURN(DRETURN dRETURN) {} + + @Override + public void visitStackInstruction(StackInstruction stackInstruction) {} + + @Override + public void visitD2L(D2L d2L) {} + + @Override + public void visitDNEG(DNEG dNEG) {} + + @Override + public void visitFCONST(FCONST fCONST) {} + + @Override + public void visitLDIV(LDIV lDIV) {} + + @Override + public void visitASTORE(ASTORE aSTORE) {} + + @Override + public void visitFREM(FREM fREM) {} + + @Override + public void visitDMUL(DMUL dMUL) {} + + @Override + public void visitFMUL(FMUL fMUL) {} + + @Override + public void visitJsrInstruction(JsrInstruction jsrInstruction) {} + + @Override + public void visitFALOAD(FALOAD fALOAD) {} + + @Override + public void visitIDIV(IDIV dIV) {} + + @Override + public void visitMULTIANEWARRAY(MULTIANEWARRAY mULTIANEWARRAY) {} + + @Override + public void visitFSTORE(FSTORE fSTORE) {} + + @Override + public void visitIUSHR(IUSHR uSHR) {} + + @Override + public void visitI2B(I2B i2B) {} + + @Override + public void visitDASTORE(DASTORE dASTORE) {} + + @Override + public void visitTypedInstruction(TypedInstruction typedInstruction) {} + + @Override + public void visitANEWARRAY(ANEWARRAY aNEWARRAY) {} + + @Override + public void visitIF_ACMPEQ(IF_ACMPEQ f_ACMPEQ) {} + + @Override + public void visitALOAD(ALOAD aLOAD) {} + + @Override + public void visitIFNE(IFNE fNE) {} + + @Override + public void visitDUP2(DUP2 dUP2) {} + + @Override + public void visitBALOAD(BALOAD bALOAD) {} + + @Override + public void visitDUP(DUP dUP) {} + + @Override + public void visitIF_ICMPLE(IF_ICMPLE f_ICMPLE) {} + + @Override + public void visitD2I(D2I d2I) {} + + @Override + public void visitARETURN(ARETURN aRETURN) {} + + @Override + public void visitI2L(I2L i2L) {} + + @Override + public void visitFADD(FADD fADD) {} + + @Override + public void visitInvokeInstruction(InvokeInstruction invokeInstruction) {} + + @Override + public void visitLCMP(LCMP lCMP) {} + + @Override + public void visitConversionInstruction(ConversionInstruction conversionInstruction) {} + + @Override + public void visitIF_ICMPLT(IF_ICMPLT f_ICMPLT) {} + + @Override + public void visitPUTSTATIC(PUTSTATIC pUTSTATIC) {} + + @Override + public void visitIFEQ(IFEQ fEQ) {} + + @Override + public void visitBIPUSH(BIPUSH bIPUSH) {} + + @Override + public void visitIFLE(IFLE fLE) {} + + @Override + public void visitReturnInstruction(ReturnInstruction returnInstruction) {} + + @Override + public void visitFRETURN(FRETURN fRETURN) {} + + @Override + public void visitStackConsumer(StackConsumer stackConsumer) {} + + @Override + public void visitGETFIELD(GETFIELD gETFIELD) {} + + @Override + public void visitIOR(IOR oR) {} + + @Override + public void visitSALOAD(SALOAD sALOAD) {} + + @Override + public void visitIFGE(IFGE fGE) {} + + @Override + public void visitIINC(IINC iNC) {} + + @Override + public void visitISHL(ISHL sHL) {} + + @Override + public void visitRET(RET rET) {} + + @Override + public void visitINVOKESPECIAL(INVOKESPECIAL nVOKESPECIAL) {} + + @Override + public void visitBASTORE(BASTORE bASTORE) {} + + @Override + public void visitAASTORE(AASTORE aASTORE) {} + + @Override + public void visitIfInstruction(IfInstruction ifInstruction) {} + + @Override + public void visitIMPDEP2(IMPDEP2 mPDEP2) {} + + @Override + public void visitPOP2(POP2 pOP2) {} + + @Override + public void visitISUB(ISUB sUB) {} + + @Override + public void visitLADD(LADD lADD) {} + + @Override + public void visitINEG(INEG nEG) {} + + @Override + public void visitINVOKESTATIC(INVOKESTATIC nVOKESTATIC) {} + + @Override + public void visitSWAP(SWAP sWAP) {} + + @Override + public void visitIFNULL(IFNULL fNULL) {} + + @Override + public void visitLoadInstruction(LoadInstruction loadInstruction) {} + + @Override + public void visitMONITORENTER(MONITORENTER mONITORENTER) {} + + @Override + public void visitJSR_W(JSR_W jSR_W) {} + + @Override + public void visitMONITOREXIT(MONITOREXIT mONITOREXIT) {} + + @Override + public void visitIRETURN(IRETURN rETURN) {} + + @Override + public void visitLCONST(LCONST lCONST) {} + + @Override + public void visitDCMPL(DCMPL dCMPL) {} + + @Override + public void visitIREM(IREM rEM) {} + + @Override + public void visitPopInstruction(PopInstruction popInstruction) {} + + @Override + public void visitDDIV(DDIV dDIV) {} + + @Override + public void visitDSUB(DSUB dSUB) {} + + @Override + public void visitDCONST(DCONST dCONST) {} + + @Override + public void visitAllocationInstruction(AllocationInstruction allocationInstruction) {} + + @Override + public void visitIALOAD(IALOAD aLOAD) {} + + @Override + public void visitI2C(I2C i2C) {} + + @Override + public void visitStackProducer(StackProducer stackProducer) {} + + @Override + public void visitCASTORE(CASTORE cASTORE) {} + + @Override + public void visitIF_ACMPNE(IF_ACMPNE f_ACMPNE) {} + + @Override + public void visitISHR(ISHR sHR) {} + + @Override + public void visitF2L(F2L f2L) {} + + @Override + public void visitSASTORE(SASTORE sASTORE) {} + + @Override + public void visitIADD(IADD aDD) {} + + @Override + public void visitFNEG(FNEG fNEG) {} + + @Override + public void visitIF_ICMPNE(IF_ICMPNE f_ICMPNE) {} + + @Override + public void visitL2D(L2D l2D) {} + + @Override + public void visitDALOAD(DALOAD dALOAD) {} + + @Override + public void visitLDC2_W(LDC2_W lDC2_W) {} + + @Override + public void visitUnconditionalBranch(UnconditionalBranch unconditionalBranch) {} + + @Override + public void visitIFNONNULL(IFNONNULL fNONNULL) {} + + @Override + public void visitL2I(L2I l2I) {} + + @Override + public void visitI2F(I2F i2F) {} + + @Override + public void visitConstantPushInstruction(ConstantPushInstruction constantPushInstruction) {} + + @Override + public void visitFSUB(FSUB fSUB) {} + + @Override + public void visitBREAKPOINT(BREAKPOINT bREAKPOINT) {} + + @Override + public void visitLASTORE(LASTORE lASTORE) {} + + @Override + public void visitLXOR(LXOR lXOR) {} + + @Override + public void visitFCMPG(FCMPG fCMPG) {} + + @Override + public void visitATHROW(ATHROW aTHROW) {} + + @Override + public void visitI2D(I2D i2D) {} + + @Override + public void visitBranchInstruction(BranchInstruction branchInstruction) {} + + @Override + public void visitFLOAD(FLOAD fLOAD) {} + + @Override + public void visitLAND(LAND lAND) {} + + @Override + public void visitSIPUSH(SIPUSH sIPUSH) {} + + @Override + public void visitCPInstruction(CPInstruction cPInstruction) {} + + @Override + public void visitLDC(LDC lDC) {} + + @Override + public void visitINVOKEINTERFACE(INVOKEINTERFACE nVOKEINTERFACE) {} + + @Override + public void visitDUP2_X2(DUP2_X2 dUP2_X2) {} + + @Override + public void visitISTORE(ISTORE sTORE) {} + + @Override + public void visitAALOAD(AALOAD aALOAD) {} + + @Override + public void visitDREM(DREM dREM) {} + + @Override + public void visitIXOR(IXOR xOR) {} + + @Override + public void visitLNEG(LNEG lNEG) {} + + @Override + public void visitDSTORE(DSTORE dSTORE) {} + + @Override + public void visitFDIV(FDIV fDIV) {} + + @Override + public void visitLREM(LREM lREM) {} + + @Override + public void visitIMPDEP1(IMPDEP1 mPDEP1) {} + + @Override + public void visitCHECKCAST(CHECKCAST cHECKCAST) {} + + @Override + public void visitF2D(F2D f2D) {} + + @Override + public void visitTABLESWITCH(TABLESWITCH tABLESWITCH) {} + + @Override + public void visitLOOKUPSWITCH(LOOKUPSWITCH lOOKUPSWITCH) {} + + @Override + public void visitDADD(DADD dADD) {} + + @Override + public void visitIFLT(IFLT fLT) {} + + @Override + public void visitDLOAD(DLOAD dLOAD) {} + + @Override + public void visitNEWARRAY(NEWARRAY nEWARRAY) {} + + @Override + public void visitIF_ICMPGT(IF_ICMPGT f_ICMPGT) {} + + @Override + public void visitDUP2_X1(DUP2_X1 dUP2_X1) {} + + @Override + public void visitIAND(IAND aND) {} + + @Override + public void visitIF_ICMPGE(IF_ICMPGE f_ICMPGE) {} + + @Override + public void visitGOTO_W(GOTO_W gOTO_W) {} + + @Override + public void visitDUP_X1(DUP_X1 dUP_X1) {} + + @Override + public void visitLSHL(LSHL lSHL) {} + + @Override + public void visitGotoInstruction(GotoInstruction gotoInstruction) {} + + @Override + public void visitFASTORE(FASTORE fASTORE) {} + + @Override + public void visitILOAD(ILOAD lOAD) {} + + @Override + public void visitF2I(F2I f2I) {} + + @Override + public void visitI2S(I2S i2S) {} + + @Override + public void visitPushInstruction(PushInstruction pushInstruction) {} + + @Override + public void visitLUSHR(LUSHR lUSHR) {} + + @Override + public void visitCALOAD(CALOAD cALOAD) {} + + @Override + public void visitLOR(LOR lOR) {} + + @Override + public void visitFCMPL(FCMPL fCMPL) {} + + @Override + public void visitLoadClass(LoadClass loadClass) {} + + @Override + public void visitRETURN(RETURN rETURN) {} + + @Override + public void visitGETSTATIC(GETSTATIC gETSTATIC) {} + + @Override + public void visitPOP(POP pOP) {} + + @Override + public void visitJSR(JSR jSR) {} + + @Override + public void visitLLOAD(LLOAD lLOAD) {} + + @Override + public void visitLMUL(LMUL lMUL) {} + + @Override + public void visitD2F(D2F d2F) {} + + @Override + public void visitINSTANCEOF(INSTANCEOF nSTANCEOF) {} + + @Override + public void visitFieldInstruction(FieldInstruction fieldInstruction) {} + + @Override + public void visitNOP(NOP nOP) {} + + @Override + public void visitIMUL(IMUL mUL) {} + + @Override + public void visitExceptionThrower(ExceptionThrower exceptionThrower) {} + + @Override + public void visitL2F(L2F l2F) {} + + @Override + public void visitPUTFIELD(PUTFIELD pUTFIELD) {} + + @Override + public void visitVariableLengthInstruction(VariableLengthInstruction variableLengthInstruction) {} + + @Override + public void visitDUP_X2(DUP_X2 dUP_X2) {} + + @Override + public void visitSelect(Select select) {} + + @Override + public void visitIASTORE(IASTORE aSTORE) {} + + @Override + public void visitLSUB(LSUB lSUB) {} + + @Override + public void visitArrayInstruction(ArrayInstruction arrayInstruction) {} + + @Override + public void visitGOTO(GOTO gOTO) {} + + @Override + public void visitIFGT(IFGT fGT) {} +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/EnumElementValueGen.java b/src/main/java/com/allatori/lib/bcel/generic/EnumElementValueGen.java new file mode 100644 index 0000000..d975261 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/EnumElementValueGen.java @@ -0,0 +1,83 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.classfile.ConstantUtf8; +import com.allatori.lib.bcel.classfile.ElementValue; +import com.allatori.lib.bcel.classfile.EnumElementValue; +import java.io.DataOutputStream; +import java.io.IOException; + +public class EnumElementValueGen extends ElementValueGen { + + public int typeIdx; + + public int valueIdx; + + public int getValueIdx() { + return this.valueIdx; + } + + public int getTypeIdx() { + return this.typeIdx; + } + + public void setTypeIdx(int typeIdx) { + this.typeIdx = typeIdx; + } + + public String getTypeIdx2() { + return ((ConstantUtf8) this.getConstantPool().getConstant(this.typeIdx)).getBytes(); + } + + public String getValueIdx2() { + return ((ConstantUtf8) this.getConstantPool().getConstant(this.valueIdx)).getBytes(); + } + + @Override + public String stringifyValue() { + return ((ConstantUtf8) this.getConstantPool().getConstant(this.valueIdx)).getBytes(); + } + + @Override + public ElementValue getElementValue() { + return new EnumElementValue( + this.type, this.typeIdx, this.valueIdx, this.cpGen.getConstantPool()); + } + + @Override + public void dump(DataOutputStream dataOutputStream) throws IOException { + dataOutputStream.writeByte(this.type); + dataOutputStream.writeShort(this.typeIdx); + dataOutputStream.writeShort(this.valueIdx); + } + + public void setValueIdx(int valueIdx) { + this.valueIdx = valueIdx; + } + + public EnumElementValueGen( + EnumElementValue enumElementValue, ConstantPoolGen constantPoolGen, boolean matches) { + super(101, constantPoolGen); + if (matches) { + this.typeIdx = constantPoolGen.addUtf8(enumElementValue.getText2()); + this.valueIdx = constantPoolGen.addUtf8(enumElementValue.getText3()); + } else { + this.typeIdx = enumElementValue.getTypeIdx(); + this.valueIdx = enumElementValue.getValueIdx(); + } + } + + public EnumElementValueGen(ObjectType objectType, String text, ConstantPoolGen constantPoolGen) { + super(101, constantPoolGen); + this.typeIdx = constantPoolGen.addUtf8(objectType.getSignature()); + this.valueIdx = constantPoolGen.addUtf8(text); + } + + public EnumElementValueGen(int typeIdx, int valueIdx, ConstantPoolGen constantPoolGen) { + super(101, constantPoolGen); + if (this.type != 101) { + throw new RuntimeException("Only element values of type enum can be built with this ctor"); + } + this.typeIdx = typeIdx; + this.valueIdx = valueIdx; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/ExceptionThrower.java b/src/main/java/com/allatori/lib/bcel/generic/ExceptionThrower.java new file mode 100644 index 0000000..84caca7 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/ExceptionThrower.java @@ -0,0 +1,6 @@ +package com.allatori.lib.bcel.generic; + +public interface ExceptionThrower { + + Class[] getExceptions(); +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/F2D.java b/src/main/java/com/allatori/lib/bcel/generic/F2D.java new file mode 100644 index 0000000..b4934cf --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/F2D.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class F2D extends ConversionInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitConversionInstruction(this); + visitor.visitF2D(this); + } + + public F2D() { + super((short) 141); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/F2I.java b/src/main/java/com/allatori/lib/bcel/generic/F2I.java new file mode 100644 index 0000000..15d7302 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/F2I.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class F2I extends ConversionInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitConversionInstruction(this); + visitor.visitF2I(this); + } + + public F2I() { + super((short) 139); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/F2L.java b/src/main/java/com/allatori/lib/bcel/generic/F2L.java new file mode 100644 index 0000000..6c392bc --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/F2L.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class F2L extends ConversionInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitConversionInstruction(this); + visitor.visitF2L(this); + } + + public F2L() { + super((short) 140); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/FADD.java b/src/main/java/com/allatori/lib/bcel/generic/FADD.java new file mode 100644 index 0000000..5713c6a --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/FADD.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class FADD extends ArithmeticInstruction { + + public FADD() { + super((short) 98); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitArithmeticInstruction(this); + visitor.visitFADD(this); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/FALOAD.java b/src/main/java/com/allatori/lib/bcel/generic/FALOAD.java new file mode 100644 index 0000000..ff190b3 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/FALOAD.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class FALOAD extends ArrayInstruction implements StackProducer { + + public FALOAD() { + super((short) 48); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitStackProducer(this); + visitor.visitExceptionThrower(this); + visitor.visitTypedInstruction(this); + visitor.visitArrayInstruction(this); + visitor.visitFALOAD(this); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/FASTORE.java b/src/main/java/com/allatori/lib/bcel/generic/FASTORE.java new file mode 100644 index 0000000..4f27945 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/FASTORE.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class FASTORE extends ArrayInstruction implements StackConsumer { + + @Override + public void accept(Visitor visitor) { + visitor.visitStackConsumer(this); + visitor.visitExceptionThrower(this); + visitor.visitTypedInstruction(this); + visitor.visitArrayInstruction(this); + visitor.visitFASTORE(this); + } + + public FASTORE() { + super((short) 81); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/FCMPG.java b/src/main/java/com/allatori/lib/bcel/generic/FCMPG.java new file mode 100644 index 0000000..955efdb --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/FCMPG.java @@ -0,0 +1,21 @@ +package com.allatori.lib.bcel.generic; + +public class FCMPG extends Instruction implements TypedInstruction, StackProducer, StackConsumer { + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitFCMPG(this); + } + + public FCMPG() { + super((short) 150, (short) 1); + } + + @Override + public Type getType(ConstantPoolGen constantPoolGen) { + return Type.FLOAT; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/FCMPL.java b/src/main/java/com/allatori/lib/bcel/generic/FCMPL.java new file mode 100644 index 0000000..961b416 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/FCMPL.java @@ -0,0 +1,21 @@ +package com.allatori.lib.bcel.generic; + +public class FCMPL extends Instruction implements TypedInstruction, StackProducer, StackConsumer { + + @Override + public Type getType(ConstantPoolGen constantPoolGen) { + return Type.FLOAT; + } + + public FCMPL() { + super((short) 149, (short) 1); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitFCMPL(this); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/FCONST.java b/src/main/java/com/allatori/lib/bcel/generic/FCONST.java new file mode 100644 index 0000000..481871d --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/FCONST.java @@ -0,0 +1,46 @@ +package com.allatori.lib.bcel.generic; + +public class FCONST extends Instruction implements ConstantPushInstruction, TypedInstruction { + + public float value; + + @Override + public void accept(Visitor visitor) { + visitor.visitPushInstruction(this); + visitor.visitStackProducer(this); + visitor.visitTypedInstruction(this); + visitor.visitConstantPushInstruction(this); + visitor.visitFCONST(this); + } + + public FCONST() {} + + @Override + public Type getType(ConstantPoolGen constantPoolGen) { + return Type.FLOAT; + } + + public FCONST(float value2) { + super((short) 11, (short) 1); + FCONST fCONST; + if (value2 == 0.0) { + fCONST = this; + this.opcode = 11; + } else if (value2 == 1.0) { + fCONST = this; + this.opcode = 12; + } else { + if (value2 != 2.0) { + throw new ClassGenException(("FCONST can be used only for 0.0, 1.0 and 2.0: " + value2)); + } + fCONST = this; + this.opcode = 13; + } + fCONST.value = value2; + } + + @Override + public Number getValue() { + return new Float(this.value); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/FDIV.java b/src/main/java/com/allatori/lib/bcel/generic/FDIV.java new file mode 100644 index 0000000..51f6767 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/FDIV.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class FDIV extends ArithmeticInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitArithmeticInstruction(this); + visitor.visitFDIV(this); + } + + public FDIV() { + super((short) 110); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/FLOAD.java b/src/main/java/com/allatori/lib/bcel/generic/FLOAD.java new file mode 100644 index 0000000..a995e19 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/FLOAD.java @@ -0,0 +1,18 @@ +package com.allatori.lib.bcel.generic; + +public class FLOAD extends LoadInstruction { + + @Override + public void accept(Visitor visitor) { + super.accept(visitor); + visitor.visitFLOAD(this); + } + + public FLOAD() { + super((short) 23, (short) 34); + } + + public FLOAD(int value) { + super((short) 23, (short) 34, value); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/FMUL.java b/src/main/java/com/allatori/lib/bcel/generic/FMUL.java new file mode 100644 index 0000000..7bda69a --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/FMUL.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class FMUL extends ArithmeticInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitArithmeticInstruction(this); + visitor.visitFMUL(this); + } + + public FMUL() { + super((short) 106); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/FNEG.java b/src/main/java/com/allatori/lib/bcel/generic/FNEG.java new file mode 100644 index 0000000..fb747b2 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/FNEG.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class FNEG extends ArithmeticInstruction { + + public FNEG() { + super((short) 118); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitArithmeticInstruction(this); + visitor.visitFNEG(this); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/FREM.java b/src/main/java/com/allatori/lib/bcel/generic/FREM.java new file mode 100644 index 0000000..8328d1c --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/FREM.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class FREM extends ArithmeticInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitArithmeticInstruction(this); + visitor.visitFREM(this); + } + + public FREM() { + super((short) 114); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/FRETURN.java b/src/main/java/com/allatori/lib/bcel/generic/FRETURN.java new file mode 100644 index 0000000..c7da9f6 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/FRETURN.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class FRETURN extends ReturnInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitExceptionThrower(this); + visitor.visitTypedInstruction(this); + visitor.visitStackConsumer(this); + visitor.visitReturnInstruction(this); + visitor.visitFRETURN(this); + } + + public FRETURN() { + super((short) 174); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/FSTORE.java b/src/main/java/com/allatori/lib/bcel/generic/FSTORE.java new file mode 100644 index 0000000..a9afb25 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/FSTORE.java @@ -0,0 +1,18 @@ +package com.allatori.lib.bcel.generic; + +public class FSTORE extends StoreInstruction { + + public FSTORE() { + super((short) 56, (short) 67); + } + + @Override + public void accept(Visitor visitor) { + super.accept(visitor); + visitor.visitFSTORE(this); + } + + public FSTORE(int value) { + super((short) 56, (short) 67, value); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/FSUB.java b/src/main/java/com/allatori/lib/bcel/generic/FSUB.java new file mode 100644 index 0000000..ce1c969 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/FSUB.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class FSUB extends ArithmeticInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitArithmeticInstruction(this); + visitor.visitFSUB(this); + } + + public FSUB() { + super((short) 102); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/FieldGen.java b/src/main/java/com/allatori/lib/bcel/generic/FieldGen.java new file mode 100644 index 0000000..f8dc14f --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/FieldGen.java @@ -0,0 +1,249 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.classfile.AnnotationEntry; +import com.allatori.lib.bcel.classfile.Annotations; +import com.allatori.lib.bcel.classfile.Attribute; +import com.allatori.lib.bcel.classfile.ConstantObject; +import com.allatori.lib.bcel.classfile.ConstantPool; +import com.allatori.lib.bcel.classfile.ConstantValue; +import com.allatori.lib.bcel.classfile.Field; +import com.allatori.lib.bcel.classfile.Utility; +import com.allatori.lib.bcel.util.BCELComparator; +import com.allatori.lib.bcel.util.comparator.FieldGenComparator; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class FieldGen extends FieldGenOrMethodGen { + + public static BCELComparator bcelComparator = new FieldGenComparator(); + + public List observers; + + public Object value; + + public void processCount2(int value2) { + this.checkType(Type.INT); + if (value2 != 0) { + this.value = new Integer(value2); + } + } + + public FieldGen(int value2, Type type, String text, ConstantPoolGen constantPoolGen) { + super(); + this.value = null; + this.setAccess_flags(value2); + this.setType(type); + this.setName(text); + this.setConstantPool(constantPoolGen); + } + + public void processCount3(int value2) { + ConstantPool constantPool; + this.value = + ((ConstantObject) (constantPool = this.cp.getConstantPool()).getConstant(value2)) + .getConstantValue(constantPool); + } + + public Field getField() { + String text = this.getText(); + int value2 = this.cp.addUtf8(this.name); + int value3 = this.cp.addUtf8(text); + if (this.value != null) { + this.checkType(this.type); + int value4 = this.addConstant(); + this.addAttribute( + new ConstantValue( + this.cp.addUtf8("ConstantValue"), 2, value4, this.cp.getConstantPool())); + } + this.addAnnotationsAsAttribute(this.cp); + return new Field( + this.access_flags, value2, value3, this.getAttributes(), this.cp.getConstantPool()); + } + + public void setInitValue(long value2) { + this.checkType(Type.LONG); + if (value2 != 0L) { + this.value = new Long(value2); + } + } + + public FieldGen copy(ConstantPoolGen constantPoolGen) { + FieldGen fieldGen = (FieldGen) this.clone(); + fieldGen.setConstantPool(constantPoolGen); + return fieldGen; + } + + public static void setComparator(BCELComparator bCELComparator) { + bcelComparator = bCELComparator; + } + + @Override + public boolean equals(Object result) { + return bcelComparator.equals(this, result); + } + + public String getInitValue() { + return this.value != null ? this.value.toString() : null; + } + + @Override + public String getText() { + return this.type.getSignature(); + } + + public void setInitValue(float value2) { + this.checkType(Type.FLOAT); + if (value2 != 0.0) { + this.value = new Float(value2); + } + } + + public void checkType(Type type2) { + if (this.type == null) { + throw new ClassGenException("You haven't defined the type of the field yet"); + } + if (!this.type.equals(type2)) { + throw new ClassGenException(("Types are not compatible: " + this.type + " vs. " + type2)); + } + } + + @Override + public int hashCode() { + return bcelComparator.hashCode(this); + } + + public void setInitValue(String value) { + this.checkType(new ObjectType("java.lang.String")); + if (value != null) { + this.value = value; + } + } + + public int addConstant() { + switch (this.type.getType()) { + case 4: + case 5: + case 8: + case 9: + case 10: + return this.cp.addInteger((Integer) this.value); + case 6: + return this.cp.addFloat((Float) this.value); + case 7: + return this.cp.addDouble((Double) this.value); + case 11: + return this.cp.addLong((Long) this.value); + case 12: + case 13: + default: + throw new RuntimeException(("Oops: Unhandled : " + this.type.getType())); + case 14: + return this.cp.addString((String) this.value); + } + } + + public static BCELComparator getComparator() { + return bcelComparator; + } + + public void setInitValue(double value2) { + this.checkType(Type.DOUBLE); + if (value2 != 0.0) { + this.value = new Double(value2); + } + } + + public void setInitValue(boolean matches) { + this.checkType(Type.BOOLEAN); + if (matches) { + this.value = new Integer(1); + } + } + + public void cancelInitValue() { + this.value = null; + } + + public void removeObserver(FieldObserver fieldObserver) { + if (this.observers != null) { + this.observers.remove(fieldObserver); + } + } + + public void addObserver(FieldObserver fieldObserver) { + if (this.observers == null) { + this.observers = new ArrayList(); + } + this.observers.add(fieldObserver); + } + + public void setInitValue(char value2) { + this.checkType(Type.CHAR); + if (value2 != 0) { + this.value = new Integer(value2); + } + } + + public void setInitValue(byte value2) { + this.checkType(Type.BYTE); + if (value2 != 0) { + this.value = new Integer(value2); + } + } + + public void addAnnotationsAsAttribute(ConstantPoolGen constantPoolGen) { + Attribute[] attributes; + int value; + if ((attributes = Utility.createAttributes(constantPoolGen, this.arrayList)) != null) { + for (int value2 = value = 0; value2 < attributes.length; value2 = value) { + int value3 = value; + Attribute[] attributes2 = attributes; + value++; + this.addAttribute(attributes2[value3]); + } + } + } + + public void setInitValue(short value2) { + this.checkType(Type.SHORT); + if (value2 != 0) { + this.value = new Integer(value2); + } + } + + public void update() { + Iterator iterator2; + if (this.observers != null) { + for (Iterator iterator3 = iterator2 = this.observers.iterator(); + iterator3.hasNext(); + iterator3 = iterator2) { + ((FieldObserver) iterator2.next()).notify(this); + } + } + } + + public FieldGen(Field field, ConstantPoolGen constantPoolGen) { + this( + field.getAccess_flags2(), Type.getType(field.getText2()), field.getText(), constantPoolGen); + Attribute[] attributes = field.getAttributes(); + int value; + for (int value2 = value = 0; value2 < attributes.length; value2 = ++value) { + if (attributes[value] instanceof ConstantValue) { + this.processCount3(((ConstantValue) attributes[value]).getConstantValueIndex()); + } else if (attributes[value] instanceof Annotations) { + AnnotationEntry[] annotationEntries = + ((Annotations) attributes[value]).getAnnotationEntries(); + int value3; + for (int value4 = value3 = 0; value4 < annotationEntries.length; value4 = value3) { + AnnotationEntry annotationEntry = annotationEntries[value3]; + value3++; + this.processAnnotationEntryGen( + new AnnotationEntryGen(annotationEntry, constantPoolGen, false)); + } + } else { + this.addAttribute(attributes[value]); + } + } + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/FieldGenOrMethodGen.java b/src/main/java/com/allatori/lib/bcel/generic/FieldGenOrMethodGen.java new file mode 100644 index 0000000..28aea75 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/FieldGenOrMethodGen.java @@ -0,0 +1,102 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.classfile.AccessFlags; +import com.allatori.lib.bcel.classfile.Attribute; +import java.util.ArrayList; +import java.util.List; + +public abstract class FieldGenOrMethodGen extends AccessFlags implements NamedAndTyped, Cloneable { + + public ArrayList arrayList; + + public List attribute_vec = new ArrayList(); + + public ConstantPoolGen cp; + + public Type type; + + public String name; + + public void setConstantPool(ConstantPoolGen constantPoolGen) { + this.cp = constantPoolGen; + } + + public void removeAttribute(Attribute attribute) { + this.attribute_vec.remove(attribute); + } + + public void addAttribute(Attribute attribute) { + this.attribute_vec.add(attribute); + } + + @Override + public void setType(Type type2) { + if (type2.getType() == 16) { + throw new IllegalArgumentException(("Type can not be " + type2)); + } + this.type = type2; + } + + public void processAnnotationEntryGen(AnnotationEntryGen annotationEntryGen) { + this.arrayList.add(annotationEntryGen); + } + + public FieldGenOrMethodGen() { + this.arrayList = new ArrayList(); + } + + @Override + public void setName(String name) { + this.name = name; + } + + @Override + public Object clone() { + try { + return super.clone(); + } catch (CloneNotSupportedException cloneNotSupportedException) { + System.err.println(cloneNotSupportedException); + return null; + } + } + + public AnnotationEntryGen[] getAnnotationEntryGens() { + AnnotationEntryGen[] annotationEntryGens = new AnnotationEntryGen[this.arrayList.size()]; + this.arrayList.toArray(annotationEntryGens); + return annotationEntryGens; + } + + @Override + public String getName() { + return this.name; + } + + @Override + public Type getType() { + return this.type; + } + + public Attribute[] getAttributes() { + Attribute[] attributes = new Attribute[this.attribute_vec.size()]; + this.attribute_vec.toArray(attributes); + return attributes; + } + + public void removeAttributes() { + this.arrayList.clear(); + } + + public void removeAttributes2() { + this.attribute_vec.clear(); + } + + public void processAnnotationEntryGen2(AnnotationEntryGen annotationEntryGen) { + this.arrayList.remove(annotationEntryGen); + } + + public ConstantPoolGen getConstantPool() { + return this.cp; + } + + public abstract String getText(); +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/FieldInstruction.java b/src/main/java/com/allatori/lib/bcel/generic/FieldInstruction.java new file mode 100644 index 0000000..e2e319a --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/FieldInstruction.java @@ -0,0 +1,35 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.Constants; +import com.allatori.lib.bcel.classfile.ConstantPool; + +public abstract class FieldInstruction extends FieldOrMethod implements TypedInstruction { + + @Override + public Type getType(ConstantPoolGen constantPoolGen) { + return this.getType2(constantPoolGen); + } + + public Type getType2(ConstantPoolGen constantPoolGen) { + return Type.getType(this.getText3(constantPoolGen)); + } + + public String getFieldName(ConstantPoolGen constantPoolGen) { + return this.getText(constantPoolGen); + } + + public FieldInstruction(short value, int value2) { + super(value, value2); + } + + public FieldInstruction() {} + + @Override + public String toString(ConstantPool constantPool) { + return "" + Constants.TEXTS8[this.opcode] + " " + constantPool.getText(this.index, (byte) 9); + } + + public int getFieldSize(ConstantPoolGen constantPoolGen) { + return this.getType(constantPoolGen).getSize(); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/FieldObserver.java b/src/main/java/com/allatori/lib/bcel/generic/FieldObserver.java new file mode 100644 index 0000000..716ff41 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/FieldObserver.java @@ -0,0 +1,6 @@ +package com.allatori.lib.bcel.generic; + +public interface FieldObserver { + + void notify(FieldGen fieldGen); +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/FieldOrMethod.java b/src/main/java/com/allatori/lib/bcel/generic/FieldOrMethod.java new file mode 100644 index 0000000..d5e2514 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/FieldOrMethod.java @@ -0,0 +1,72 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.classfile.ConstantCP; +import com.allatori.lib.bcel.classfile.ConstantNameAndType; +import com.allatori.lib.bcel.classfile.ConstantPool; +import com.allatori.lib.bcel.classfile.ConstantUtf8; + +public abstract class FieldOrMethod extends CPInstruction implements LoadClass { + + public FieldOrMethod(short value, int value2) { + super(value, value2); + } + + public ReferenceType getReferenceType(ConstantPoolGen constantPoolGen) { + ConstantPool constantPool; + ConstantCP constantCP = + (ConstantCP) (constantPool = constantPoolGen.getConstantPool()).getConstant(this.index); + String text; + if ((text = constantPool.createText(constantCP.getClass_index(), (byte) 7)).startsWith("[")) { + return (ArrayType) Type.getType(text); + } + String text2 = text.replace('/', '.'); + return new ObjectType(text2); + } + + /** + * @deprecated + */ + public ObjectType createObjectType(ConstantPoolGen constantPoolGen) { + return new ObjectType(this.getText2(constantPoolGen)); + } + + @Override + public ObjectType getLoadClassType(ConstantPoolGen constantPoolGen) { + return this.createObjectType(constantPoolGen); + } + + public FieldOrMethod() {} + + public String getText(ConstantPoolGen constantPoolGen) { + ConstantPool constantPool; + ConstantCP constantCP = + (ConstantCP) (constantPool = constantPoolGen.getConstantPool()).getConstant(this.index); + ConstantNameAndType constantNameAndType = + (ConstantNameAndType) constantPool.getConstant(constantCP.getName_and_type_index()); + return ((ConstantUtf8) constantPool.getConstant(constantNameAndType.getName_index())) + .getBytes(); + } + + /** + * @deprecated + */ + public String getText2(ConstantPoolGen constantPoolGen) { + ConstantPool constantPool; + ConstantCP constantCP = + (ConstantCP) (constantPool = constantPoolGen.getConstantPool()).getConstant(this.index); + String text; + return (text = constantPool.createText(constantCP.getClass_index(), (byte) 7)).startsWith("[") + ? "java.lang.Object" + : text.replace('/', '.'); + } + + public String getText3(ConstantPoolGen constantPoolGen) { + ConstantPool constantPool; + ConstantCP constantCP = + (ConstantCP) (constantPool = constantPoolGen.getConstantPool()).getConstant(this.index); + ConstantNameAndType constantNameAndType = + (ConstantNameAndType) constantPool.getConstant(constantCP.getName_and_type_index()); + return ((ConstantUtf8) constantPool.getConstant(constantNameAndType.getSignature_index())) + .getBytes(); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/GETFIELD.java b/src/main/java/com/allatori/lib/bcel/generic/GETFIELD.java new file mode 100644 index 0000000..253508d --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/GETFIELD.java @@ -0,0 +1,40 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.ExceptionConstants; + +public class GETFIELD extends FieldInstruction + implements ExceptionThrower, StackConsumer, StackProducer { + + @Override + public void accept(Visitor visitor) { + visitor.visitExceptionThrower(this); + visitor.visitStackConsumer(this); + visitor.visitStackProducer(this); + visitor.visitTypedInstruction(this); + visitor.visitLoadClass(this); + visitor.visitCPInstruction(this); + visitor.visitFieldOrMethod(this); + visitor.visitFieldInstruction(this); + visitor.visitGETFIELD(this); + } + + public GETFIELD(int value) { + super((short) 180, value); + } + + @Override + public Class[] getExceptions() { + Class[] classs = new Class[2 + ExceptionConstants.TYPES2.length]; + System.arraycopy(ExceptionConstants.TYPES2, 0, classs, 0, ExceptionConstants.TYPES2.length); + classs[ExceptionConstants.TYPES2.length + 1] = ExceptionConstants.TYPE9; + classs[ExceptionConstants.TYPES2.length] = ExceptionConstants.TYPE3; + return classs; + } + + public GETFIELD() {} + + @Override + public int produceStack(ConstantPoolGen constantPoolGen) { + return this.getFieldSize(constantPoolGen); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/GETSTATIC.java b/src/main/java/com/allatori/lib/bcel/generic/GETSTATIC.java new file mode 100644 index 0000000..eb54795 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/GETSTATIC.java @@ -0,0 +1,38 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.ExceptionConstants; + +public class GETSTATIC extends FieldInstruction implements PushInstruction, ExceptionThrower { + + public GETSTATIC(int value) { + super((short) 178, value); + } + + @Override + public Class[] getExceptions() { + Class[] classs = new Class[1 + ExceptionConstants.TYPES2.length]; + System.arraycopy(ExceptionConstants.TYPES2, 0, classs, 0, ExceptionConstants.TYPES2.length); + classs[ExceptionConstants.TYPES2.length] = ExceptionConstants.TYPE9; + return classs; + } + + public GETSTATIC() {} + + @Override + public int produceStack(ConstantPoolGen constantPoolGen) { + return this.getFieldSize(constantPoolGen); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitStackProducer(this); + visitor.visitPushInstruction(this); + visitor.visitExceptionThrower(this); + visitor.visitTypedInstruction(this); + visitor.visitLoadClass(this); + visitor.visitCPInstruction(this); + visitor.visitFieldOrMethod(this); + visitor.visitFieldInstruction(this); + visitor.visitGETSTATIC(this); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/GOTO.java b/src/main/java/com/allatori/lib/bcel/generic/GOTO.java new file mode 100644 index 0000000..4c0ae81 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/GOTO.java @@ -0,0 +1,47 @@ +package com.allatori.lib.bcel.generic; + +import java.io.DataOutputStream; +import java.io.IOException; + +public class GOTO extends GotoInstruction implements VariableLengthInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitVariableLengthInstruction(this); + visitor.visitUnconditionalBranch(this); + visitor.visitBranchInstruction(this); + visitor.visitGotoInstruction(this); + visitor.visitGOTO(this); + } + + @Override + public void dump(DataOutputStream dataOutputStream) throws IOException { + this.index = this.getTargetOffset(); + if (this.opcode == 167) { + super.dump(dataOutputStream); + } else { + this.index = this.getTargetOffset(); + dataOutputStream.writeByte(this.opcode); + dataOutputStream.writeInt(this.index); + } + } + + public GOTO(InstructionHandle instructionHandle) { + super((short) 167, instructionHandle); + } + + @Override + public int updatePosition(int count, int value2) { + int targetOffset = this.getTargetOffset(); + this.count += count; + if (Math.abs(targetOffset) >= 32767 - value2) { + this.opcode = 200; + this.length = 5; + return 2; + } else { + return 0; + } + } + + public GOTO() {} +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/GOTO_W.java b/src/main/java/com/allatori/lib/bcel/generic/GOTO_W.java new file mode 100644 index 0000000..50e2efe --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/GOTO_W.java @@ -0,0 +1,36 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.util.ByteSequence; +import java.io.DataOutputStream; +import java.io.IOException; + +public class GOTO_W extends GotoInstruction { + + public GOTO_W(InstructionHandle instructionHandle) { + super((short) 200, instructionHandle); + this.length = 5; + } + + @Override + public void initFromFile(ByteSequence byteSequence, boolean matches) throws IOException { + this.index = byteSequence.readInt(); + this.length = 5; + } + + @Override + public void dump(DataOutputStream dataOutputStream) throws IOException { + this.index = this.getTargetOffset(); + dataOutputStream.writeByte(this.opcode); + dataOutputStream.writeInt(this.index); + } + + public GOTO_W() {} + + @Override + public void accept(Visitor visitor) { + visitor.visitUnconditionalBranch(this); + visitor.visitBranchInstruction(this); + visitor.visitGotoInstruction(this); + visitor.visitGOTO_W(this); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/GotoInstruction.java b/src/main/java/com/allatori/lib/bcel/generic/GotoInstruction.java new file mode 100644 index 0000000..01f980b --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/GotoInstruction.java @@ -0,0 +1,10 @@ +package com.allatori.lib.bcel.generic; + +public abstract class GotoInstruction extends BranchInstruction implements UnconditionalBranch { + + public GotoInstruction() {} + + public GotoInstruction(short value, InstructionHandle instructionHandle) { + super(value, instructionHandle); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/I2B.java b/src/main/java/com/allatori/lib/bcel/generic/I2B.java new file mode 100644 index 0000000..ef007f2 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/I2B.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class I2B extends ConversionInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitConversionInstruction(this); + visitor.visitI2B(this); + } + + public I2B() { + super((short) 145); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/I2C.java b/src/main/java/com/allatori/lib/bcel/generic/I2C.java new file mode 100644 index 0000000..588e941 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/I2C.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class I2C extends ConversionInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitConversionInstruction(this); + visitor.visitI2C(this); + } + + public I2C() { + super((short) 146); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/I2D.java b/src/main/java/com/allatori/lib/bcel/generic/I2D.java new file mode 100644 index 0000000..2561c83 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/I2D.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class I2D extends ConversionInstruction { + + public I2D() { + super((short) 135); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitConversionInstruction(this); + visitor.visitI2D(this); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/I2F.java b/src/main/java/com/allatori/lib/bcel/generic/I2F.java new file mode 100644 index 0000000..b6815fb --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/I2F.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class I2F extends ConversionInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitConversionInstruction(this); + visitor.visitI2F(this); + } + + public I2F() { + super((short) 134); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/I2L.java b/src/main/java/com/allatori/lib/bcel/generic/I2L.java new file mode 100644 index 0000000..479f9a8 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/I2L.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class I2L extends ConversionInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitConversionInstruction(this); + visitor.visitI2L(this); + } + + public I2L() { + super((short) 133); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/I2S.java b/src/main/java/com/allatori/lib/bcel/generic/I2S.java new file mode 100644 index 0000000..852723d --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/I2S.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class I2S extends ConversionInstruction { + + public I2S() { + super((short) 147); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitConversionInstruction(this); + visitor.visitI2S(this); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/IADD.java b/src/main/java/com/allatori/lib/bcel/generic/IADD.java new file mode 100644 index 0000000..2ffeea8 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/IADD.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class IADD extends ArithmeticInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitArithmeticInstruction(this); + visitor.visitIADD(this); + } + + public IADD() { + super((short) 96); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/IALOAD.java b/src/main/java/com/allatori/lib/bcel/generic/IALOAD.java new file mode 100644 index 0000000..29471ec --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/IALOAD.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class IALOAD extends ArrayInstruction implements StackProducer { + + public IALOAD() { + super((short) 46); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitStackProducer(this); + visitor.visitExceptionThrower(this); + visitor.visitTypedInstruction(this); + visitor.visitArrayInstruction(this); + visitor.visitIALOAD(this); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/IAND.java b/src/main/java/com/allatori/lib/bcel/generic/IAND.java new file mode 100644 index 0000000..e882e59 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/IAND.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class IAND extends ArithmeticInstruction { + + public IAND() { + super((short) 126); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitArithmeticInstruction(this); + visitor.visitIAND(this); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/IASTORE.java b/src/main/java/com/allatori/lib/bcel/generic/IASTORE.java new file mode 100644 index 0000000..808aef8 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/IASTORE.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class IASTORE extends ArrayInstruction implements StackConsumer { + + @Override + public void accept(Visitor visitor) { + visitor.visitStackConsumer(this); + visitor.visitExceptionThrower(this); + visitor.visitTypedInstruction(this); + visitor.visitArrayInstruction(this); + visitor.visitIASTORE(this); + } + + public IASTORE() { + super((short) 79); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/ICONST.java b/src/main/java/com/allatori/lib/bcel/generic/ICONST.java new file mode 100644 index 0000000..0e730ed --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/ICONST.java @@ -0,0 +1,37 @@ +package com.allatori.lib.bcel.generic; + +public class ICONST extends Instruction implements ConstantPushInstruction, TypedInstruction { + + public int value; + + @Override + public void accept(Visitor visitor) { + visitor.visitPushInstruction(this); + visitor.visitStackProducer(this); + visitor.visitTypedInstruction(this); + visitor.visitConstantPushInstruction(this); + visitor.visitICONST(this); + } + + public ICONST(int value) { + super((short) 3, (short) 1); + if (value >= -1 && value <= 5) { + this.opcode = (short) (3 + value); + this.value = value; + } else { + throw new ClassGenException(("ICONST can be used only for value between -1 and 5: " + value)); + } + } + + @Override + public Number getValue() { + return new Integer(this.value); + } + + @Override + public Type getType(ConstantPoolGen constantPoolGen) { + return Type.INT; + } + + public ICONST() {} +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/IDIV.java b/src/main/java/com/allatori/lib/bcel/generic/IDIV.java new file mode 100644 index 0000000..2b26214 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/IDIV.java @@ -0,0 +1,25 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.ExceptionConstants; + +public class IDIV extends ArithmeticInstruction implements ExceptionThrower { + + @Override + public Class[] getExceptions() { + return new Class[] {ExceptionConstants.TYPE18}; + } + + public IDIV() { + super((short) 108); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitExceptionThrower(this); + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitArithmeticInstruction(this); + visitor.visitIDIV(this); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/IFEQ.java b/src/main/java/com/allatori/lib/bcel/generic/IFEQ.java new file mode 100644 index 0000000..bcac007 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/IFEQ.java @@ -0,0 +1,23 @@ +package com.allatori.lib.bcel.generic; + +public class IFEQ extends IfInstruction { + + public IFEQ(InstructionHandle instructionHandle) { + super((short) 153, instructionHandle); + } + + @Override + public IfInstruction negate() { + return new IFNE(this.target); + } + + public IFEQ() {} + + @Override + public void accept(Visitor visitor) { + visitor.visitStackConsumer(this); + visitor.visitBranchInstruction(this); + visitor.visitIfInstruction(this); + visitor.visitIFEQ(this); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/IFGE.java b/src/main/java/com/allatori/lib/bcel/generic/IFGE.java new file mode 100644 index 0000000..a4a1dca --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/IFGE.java @@ -0,0 +1,23 @@ +package com.allatori.lib.bcel.generic; + +public class IFGE extends IfInstruction { + + public IFGE(InstructionHandle instructionHandle) { + super((short) 156, instructionHandle); + } + + @Override + public IfInstruction negate() { + return new IFLT(this.target); + } + + public IFGE() {} + + @Override + public void accept(Visitor visitor) { + visitor.visitStackConsumer(this); + visitor.visitBranchInstruction(this); + visitor.visitIfInstruction(this); + visitor.visitIFGE(this); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/IFGT.java b/src/main/java/com/allatori/lib/bcel/generic/IFGT.java new file mode 100644 index 0000000..5226503 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/IFGT.java @@ -0,0 +1,23 @@ +package com.allatori.lib.bcel.generic; + +public class IFGT extends IfInstruction { + + @Override + public IfInstruction negate() { + return new IFLE(this.target); + } + + public IFGT() {} + + @Override + public void accept(Visitor visitor) { + visitor.visitStackConsumer(this); + visitor.visitBranchInstruction(this); + visitor.visitIfInstruction(this); + visitor.visitIFGT(this); + } + + public IFGT(InstructionHandle instructionHandle) { + super((short) 157, instructionHandle); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/IFLE.java b/src/main/java/com/allatori/lib/bcel/generic/IFLE.java new file mode 100644 index 0000000..8c9cb41 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/IFLE.java @@ -0,0 +1,23 @@ +package com.allatori.lib.bcel.generic; + +public class IFLE extends IfInstruction { + + public IFLE(InstructionHandle instructionHandle) { + super((short) 158, instructionHandle); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitStackConsumer(this); + visitor.visitBranchInstruction(this); + visitor.visitIfInstruction(this); + visitor.visitIFLE(this); + } + + @Override + public IfInstruction negate() { + return new IFGT(this.target); + } + + public IFLE() {} +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/IFLT.java b/src/main/java/com/allatori/lib/bcel/generic/IFLT.java new file mode 100644 index 0000000..264f68c --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/IFLT.java @@ -0,0 +1,23 @@ +package com.allatori.lib.bcel.generic; + +public class IFLT extends IfInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitStackConsumer(this); + visitor.visitBranchInstruction(this); + visitor.visitIfInstruction(this); + visitor.visitIFLT(this); + } + + public IFLT() {} + + @Override + public IfInstruction negate() { + return new IFGE(this.target); + } + + public IFLT(InstructionHandle instructionHandle) { + super((short) 155, instructionHandle); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/IFNE.java b/src/main/java/com/allatori/lib/bcel/generic/IFNE.java new file mode 100644 index 0000000..ef967d6 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/IFNE.java @@ -0,0 +1,23 @@ +package com.allatori.lib.bcel.generic; + +public class IFNE extends IfInstruction { + + @Override + public IfInstruction negate() { + return new IFEQ(this.target); + } + + public IFNE() {} + + @Override + public void accept(Visitor visitor) { + visitor.visitStackConsumer(this); + visitor.visitBranchInstruction(this); + visitor.visitIfInstruction(this); + visitor.visitIFNE(this); + } + + public IFNE(InstructionHandle instructionHandle) { + super((short) 154, instructionHandle); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/IFNONNULL.java b/src/main/java/com/allatori/lib/bcel/generic/IFNONNULL.java new file mode 100644 index 0000000..88c3aad --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/IFNONNULL.java @@ -0,0 +1,23 @@ +package com.allatori.lib.bcel.generic; + +public class IFNONNULL extends IfInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitStackConsumer(this); + visitor.visitBranchInstruction(this); + visitor.visitIfInstruction(this); + visitor.visitIFNONNULL(this); + } + + @Override + public IfInstruction negate() { + return new IFNULL(this.target); + } + + public IFNONNULL(InstructionHandle instructionHandle) { + super((short) 199, instructionHandle); + } + + public IFNONNULL() {} +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/IFNULL.java b/src/main/java/com/allatori/lib/bcel/generic/IFNULL.java new file mode 100644 index 0000000..05e3165 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/IFNULL.java @@ -0,0 +1,23 @@ +package com.allatori.lib.bcel.generic; + +public class IFNULL extends IfInstruction { + + @Override + public IfInstruction negate() { + return new IFNONNULL(this.target); + } + + public IFNULL(InstructionHandle instructionHandle) { + super((short) 198, instructionHandle); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitStackConsumer(this); + visitor.visitBranchInstruction(this); + visitor.visitIfInstruction(this); + visitor.visitIFNULL(this); + } + + public IFNULL() {} +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/IF_ACMPEQ.java b/src/main/java/com/allatori/lib/bcel/generic/IF_ACMPEQ.java new file mode 100644 index 0000000..64a4eb9 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/IF_ACMPEQ.java @@ -0,0 +1,23 @@ +package com.allatori.lib.bcel.generic; + +public class IF_ACMPEQ extends IfInstruction { + + @Override + public IfInstruction negate() { + return new IF_ACMPNE(this.target); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitStackConsumer(this); + visitor.visitBranchInstruction(this); + visitor.visitIfInstruction(this); + visitor.visitIF_ACMPEQ(this); + } + + public IF_ACMPEQ(InstructionHandle instructionHandle) { + super((short) 165, instructionHandle); + } + + public IF_ACMPEQ() {} +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/IF_ACMPNE.java b/src/main/java/com/allatori/lib/bcel/generic/IF_ACMPNE.java new file mode 100644 index 0000000..67e6da2 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/IF_ACMPNE.java @@ -0,0 +1,23 @@ +package com.allatori.lib.bcel.generic; + +public class IF_ACMPNE extends IfInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitStackConsumer(this); + visitor.visitBranchInstruction(this); + visitor.visitIfInstruction(this); + visitor.visitIF_ACMPNE(this); + } + + public IF_ACMPNE(InstructionHandle instructionHandle) { + super((short) 166, instructionHandle); + } + + @Override + public IfInstruction negate() { + return new IF_ACMPEQ(this.target); + } + + public IF_ACMPNE() {} +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/IF_ICMPEQ.java b/src/main/java/com/allatori/lib/bcel/generic/IF_ICMPEQ.java new file mode 100644 index 0000000..edeb426 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/IF_ICMPEQ.java @@ -0,0 +1,23 @@ +package com.allatori.lib.bcel.generic; + +public class IF_ICMPEQ extends IfInstruction { + + public IF_ICMPEQ() {} + + @Override + public IfInstruction negate() { + return new IF_ICMPNE(this.target); + } + + public IF_ICMPEQ(InstructionHandle instructionHandle) { + super((short) 159, instructionHandle); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitStackConsumer(this); + visitor.visitBranchInstruction(this); + visitor.visitIfInstruction(this); + visitor.visitIF_ICMPEQ(this); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/IF_ICMPGE.java b/src/main/java/com/allatori/lib/bcel/generic/IF_ICMPGE.java new file mode 100644 index 0000000..fbf51b1 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/IF_ICMPGE.java @@ -0,0 +1,23 @@ +package com.allatori.lib.bcel.generic; + +public class IF_ICMPGE extends IfInstruction { + + public IF_ICMPGE() {} + + @Override + public IfInstruction negate() { + return new IF_ICMPLT(this.target); + } + + public IF_ICMPGE(InstructionHandle instructionHandle) { + super((short) 162, instructionHandle); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitStackConsumer(this); + visitor.visitBranchInstruction(this); + visitor.visitIfInstruction(this); + visitor.visitIF_ICMPGE(this); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/IF_ICMPGT.java b/src/main/java/com/allatori/lib/bcel/generic/IF_ICMPGT.java new file mode 100644 index 0000000..291d4b8 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/IF_ICMPGT.java @@ -0,0 +1,23 @@ +package com.allatori.lib.bcel.generic; + +public class IF_ICMPGT extends IfInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitStackConsumer(this); + visitor.visitBranchInstruction(this); + visitor.visitIfInstruction(this); + visitor.visitIF_ICMPGT(this); + } + + public IF_ICMPGT() {} + + @Override + public IfInstruction negate() { + return new IF_ICMPLE(this.target); + } + + public IF_ICMPGT(InstructionHandle instructionHandle) { + super((short) 163, instructionHandle); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/IF_ICMPLE.java b/src/main/java/com/allatori/lib/bcel/generic/IF_ICMPLE.java new file mode 100644 index 0000000..11db6c1 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/IF_ICMPLE.java @@ -0,0 +1,23 @@ +package com.allatori.lib.bcel.generic; + +public class IF_ICMPLE extends IfInstruction { + + @Override + public IfInstruction negate() { + return new IF_ICMPGT(this.target); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitStackConsumer(this); + visitor.visitBranchInstruction(this); + visitor.visitIfInstruction(this); + visitor.visitIF_ICMPLE(this); + } + + public IF_ICMPLE(InstructionHandle instructionHandle) { + super((short) 164, instructionHandle); + } + + public IF_ICMPLE() {} +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/IF_ICMPLT.java b/src/main/java/com/allatori/lib/bcel/generic/IF_ICMPLT.java new file mode 100644 index 0000000..c73c877 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/IF_ICMPLT.java @@ -0,0 +1,23 @@ +package com.allatori.lib.bcel.generic; + +public class IF_ICMPLT extends IfInstruction { + + @Override + public IfInstruction negate() { + return new IF_ICMPGE(this.target); + } + + public IF_ICMPLT() {} + + @Override + public void accept(Visitor visitor) { + visitor.visitStackConsumer(this); + visitor.visitBranchInstruction(this); + visitor.visitIfInstruction(this); + visitor.visitIF_ICMPLT(this); + } + + public IF_ICMPLT(InstructionHandle instructionHandle) { + super((short) 161, instructionHandle); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/IF_ICMPNE.java b/src/main/java/com/allatori/lib/bcel/generic/IF_ICMPNE.java new file mode 100644 index 0000000..1cf851c --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/IF_ICMPNE.java @@ -0,0 +1,23 @@ +package com.allatori.lib.bcel.generic; + +public class IF_ICMPNE extends IfInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitStackConsumer(this); + visitor.visitBranchInstruction(this); + visitor.visitIfInstruction(this); + visitor.visitIF_ICMPNE(this); + } + + @Override + public IfInstruction negate() { + return new IF_ICMPEQ(this.target); + } + + public IF_ICMPNE() {} + + public IF_ICMPNE(InstructionHandle instructionHandle) { + super((short) 160, instructionHandle); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/IINC.java b/src/main/java/com/allatori/lib/bcel/generic/IINC.java new file mode 100644 index 0000000..3afc519 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/IINC.java @@ -0,0 +1,93 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.util.ByteSequence; +import java.io.DataOutputStream; +import java.io.IOException; + +public class IINC extends LocalVariableInstruction { + + public boolean wide; + + public int c; + + public final void setIncrement(int c) { + this.c = c; + this.setWide(); + } + + public IINC() {} + + @Override + public String toString(boolean matches) { + return "" + super.toString(matches) + " " + this.c; + } + + public IINC(int value, int value2) { + super(); + this.opcode = 132; + this.length = 3; + this.setIndex(value); + this.setIncrement(value2); + } + + @Override + public final void setIndex(int n) { + if (n < 0) { + throw new ClassGenException(("Negative index value: " + n)); + } + this.n = n; + this.setWide(); + } + + @Override + public void initFromFile(ByteSequence byteSequence, boolean wide) throws IOException { + if (this.wide = wide) { + this.length = 6; + this.n = byteSequence.readUnsignedShort(); + this.c = byteSequence.readShort(); + } else { + this.length = 3; + this.n = byteSequence.readUnsignedByte(); + this.c = byteSequence.readByte(); + } + } + + @Override + public void dump(DataOutputStream dataOutputStream) throws IOException { + if (this.wide) { + dataOutputStream.writeByte(196); + } + dataOutputStream.writeByte(this.opcode); + if (this.wide) { + dataOutputStream.writeShort(this.n); + dataOutputStream.writeShort(this.c); + } else { + dataOutputStream.writeByte(this.n); + dataOutputStream.writeByte(this.c); + } + } + + @Override + public Type getType(ConstantPoolGen constantPoolGen) { + return Type.INT; + } + + @Override + public void accept(Visitor visitor) { + visitor.visitLocalVariableInstruction(this); + visitor.visitIINC(this); + } + + public final int getIncrement() { + return this.c; + } + + public final void setWide() { + this.wide = this.n > 255 || Math.abs(this.c) > 127; + if (this.wide) { + this.length = 6; + } else { + this.length = 3; + } + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/ILOAD.java b/src/main/java/com/allatori/lib/bcel/generic/ILOAD.java new file mode 100644 index 0000000..24152c9 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/ILOAD.java @@ -0,0 +1,18 @@ +package com.allatori.lib.bcel.generic; + +public class ILOAD extends LoadInstruction { + + public ILOAD(int value) { + super((short) 21, (short) 26, value); + } + + @Override + public void accept(Visitor visitor) { + super.accept(visitor); + visitor.visitILOAD(this); + } + + public ILOAD() { + super((short) 21, (short) 26); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/IMPDEP1.java b/src/main/java/com/allatori/lib/bcel/generic/IMPDEP1.java new file mode 100644 index 0000000..6cb43ee --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/IMPDEP1.java @@ -0,0 +1,13 @@ +package com.allatori.lib.bcel.generic; + +public class IMPDEP1 extends Instruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitIMPDEP1(this); + } + + public IMPDEP1() { + super((short) 254, (short) 1); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/IMPDEP2.java b/src/main/java/com/allatori/lib/bcel/generic/IMPDEP2.java new file mode 100644 index 0000000..1aaf3f6 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/IMPDEP2.java @@ -0,0 +1,13 @@ +package com.allatori.lib.bcel.generic; + +public class IMPDEP2 extends Instruction { + + public IMPDEP2() { + super((short) 255, (short) 1); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitIMPDEP2(this); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/IMUL.java b/src/main/java/com/allatori/lib/bcel/generic/IMUL.java new file mode 100644 index 0000000..bfbd721 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/IMUL.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class IMUL extends ArithmeticInstruction { + + public IMUL() { + super((short) 104); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitArithmeticInstruction(this); + visitor.visitIMUL(this); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/INEG.java b/src/main/java/com/allatori/lib/bcel/generic/INEG.java new file mode 100644 index 0000000..0ee5d27 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/INEG.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class INEG extends ArithmeticInstruction { + + public INEG() { + super((short) 116); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitArithmeticInstruction(this); + visitor.visitINEG(this); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/INSTANCEOF.java b/src/main/java/com/allatori/lib/bcel/generic/INSTANCEOF.java new file mode 100644 index 0000000..df8c5dc --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/INSTANCEOF.java @@ -0,0 +1,38 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.ExceptionConstants; + +public class INSTANCEOF extends CPInstruction + implements LoadClass, ExceptionThrower, StackProducer, StackConsumer { + + @Override + public void accept(Visitor visitor) { + visitor.visitLoadClass(this); + visitor.visitExceptionThrower(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitTypedInstruction(this); + visitor.visitCPInstruction(this); + visitor.visitINSTANCEOF(this); + } + + public INSTANCEOF(int value) { + super((short) 193, value); + } + + @Override + public Class[] getExceptions() { + return ExceptionConstants.TYPES5; + } + + @Override + public ObjectType getLoadClassType(ConstantPoolGen constantPoolGen) { + Type type; + if ((type = this.getType(constantPoolGen)) instanceof ArrayType) { + type = ((ArrayType) type).getBasicType(); + } + return type instanceof ObjectType ? (ObjectType) type : null; + } + + public INSTANCEOF() {} +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/INVOKEINTERFACE.java b/src/main/java/com/allatori/lib/bcel/generic/INVOKEINTERFACE.java new file mode 100644 index 0000000..d3434bc --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/INVOKEINTERFACE.java @@ -0,0 +1,77 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.ExceptionConstants; +import com.allatori.lib.bcel.classfile.ConstantPool; +import com.allatori.lib.bcel.util.ByteSequence; +import java.io.DataOutputStream; +import java.io.IOException; + +public final class INVOKEINTERFACE extends InvokeInstruction { + + public int nargs; + + @Override + public String toString(ConstantPool constantPool) { + return "" + super.toString(constantPool) + " " + this.nargs; + } + + @Override + public void accept(Visitor visitor) { + visitor.visitExceptionThrower(this); + visitor.visitTypedInstruction(this); + visitor.visitStackConsumer(this); + visitor.visitStackProducer(this); + visitor.visitLoadClass(this); + visitor.visitCPInstruction(this); + visitor.visitFieldOrMethod(this); + visitor.visitInvokeInstruction(this); + visitor.visitINVOKEINTERFACE(this); + } + + @Override + public int consumeStack(ConstantPoolGen constantPoolGen) { + return this.nargs; + } + + public INVOKEINTERFACE() {} + + @Override + public void initFromFile(ByteSequence byteSequence, boolean matches) throws IOException { + super.initFromFile(byteSequence, matches); + this.length = 5; + this.nargs = byteSequence.readUnsignedByte(); + byteSequence.readByte(); + } + + @Override + public Class[] getExceptions() { + Class[] classs = new Class[4 + ExceptionConstants.TYPES4.length]; + System.arraycopy(ExceptionConstants.TYPES4, 0, classs, 0, ExceptionConstants.TYPES4.length); + classs[ExceptionConstants.TYPES4.length + 3] = ExceptionConstants.TYPE9; + classs[ExceptionConstants.TYPES4.length + 2] = ExceptionConstants.TYPE7; + classs[ExceptionConstants.TYPES4.length + 1] = ExceptionConstants.TYPE14; + classs[ExceptionConstants.TYPES4.length] = ExceptionConstants.TYPE6; + return classs; + } + + public INVOKEINTERFACE(int value, int nargs) { + super((short) 185, value); + this.length = 5; + if (nargs < 1) { + throw new ClassGenException(("Number of arguments must be > 0 " + nargs)); + } + this.nargs = nargs; + } + + @Override + public void dump(DataOutputStream dataOutputStream) throws IOException { + dataOutputStream.writeByte(this.opcode); + dataOutputStream.writeShort(this.index); + dataOutputStream.writeByte(this.nargs); + dataOutputStream.writeByte(0); + } + + public int getCount() { + return this.nargs; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/INVOKESPECIAL.java b/src/main/java/com/allatori/lib/bcel/generic/INVOKESPECIAL.java new file mode 100644 index 0000000..791f8de --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/INVOKESPECIAL.java @@ -0,0 +1,36 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.ExceptionConstants; + +public class INVOKESPECIAL extends InvokeInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitExceptionThrower(this); + visitor.visitTypedInstruction(this); + visitor.visitStackConsumer(this); + visitor.visitStackProducer(this); + visitor.visitLoadClass(this); + visitor.visitCPInstruction(this); + visitor.visitFieldOrMethod(this); + visitor.visitInvokeInstruction(this); + visitor.visitINVOKESPECIAL(this); + } + + @Override + public Class[] getExceptions() { + Class[] classs = new Class[4 + ExceptionConstants.TYPES2.length]; + System.arraycopy(ExceptionConstants.TYPES2, 0, classs, 0, ExceptionConstants.TYPES2.length); + classs[ExceptionConstants.TYPES2.length + 3] = ExceptionConstants.TYPE6; + classs[ExceptionConstants.TYPES2.length + 2] = ExceptionConstants.TYPE14; + classs[ExceptionConstants.TYPES2.length + 1] = ExceptionConstants.TYPE9; + classs[ExceptionConstants.TYPES2.length] = ExceptionConstants.TYPE3; + return classs; + } + + public INVOKESPECIAL() {} + + public INVOKESPECIAL(int value) { + super((short) 183, value); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/INVOKESTATIC.java b/src/main/java/com/allatori/lib/bcel/generic/INVOKESTATIC.java new file mode 100644 index 0000000..ed71da3 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/INVOKESTATIC.java @@ -0,0 +1,34 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.ExceptionConstants; + +public class INVOKESTATIC extends InvokeInstruction { + + public INVOKESTATIC() {} + + @Override + public Class[] getExceptions() { + Class[] classs = new Class[2 + ExceptionConstants.TYPES2.length]; + System.arraycopy(ExceptionConstants.TYPES2, 0, classs, 0, ExceptionConstants.TYPES2.length); + classs[ExceptionConstants.TYPES2.length] = ExceptionConstants.TYPE6; + classs[ExceptionConstants.TYPES2.length + 1] = ExceptionConstants.TYPE9; + return classs; + } + + public INVOKESTATIC(int value) { + super((short) 184, value); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitExceptionThrower(this); + visitor.visitTypedInstruction(this); + visitor.visitStackConsumer(this); + visitor.visitStackProducer(this); + visitor.visitLoadClass(this); + visitor.visitCPInstruction(this); + visitor.visitFieldOrMethod(this); + visitor.visitInvokeInstruction(this); + visitor.visitINVOKESTATIC(this); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/INVOKEVIRTUAL.java b/src/main/java/com/allatori/lib/bcel/generic/INVOKEVIRTUAL.java new file mode 100644 index 0000000..75c9655 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/INVOKEVIRTUAL.java @@ -0,0 +1,36 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.ExceptionConstants; + +public class INVOKEVIRTUAL extends InvokeInstruction { + + public INVOKEVIRTUAL(int value) { + super((short) 182, value); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitExceptionThrower(this); + visitor.visitTypedInstruction(this); + visitor.visitStackConsumer(this); + visitor.visitStackProducer(this); + visitor.visitLoadClass(this); + visitor.visitCPInstruction(this); + visitor.visitFieldOrMethod(this); + visitor.visitInvokeInstruction(this); + visitor.visitINVOKEVIRTUAL(this); + } + + public INVOKEVIRTUAL() {} + + @Override + public Class[] getExceptions() { + Class[] classs = new Class[4 + ExceptionConstants.TYPES2.length]; + System.arraycopy(ExceptionConstants.TYPES2, 0, classs, 0, ExceptionConstants.TYPES2.length); + classs[ExceptionConstants.TYPES2.length + 3] = ExceptionConstants.TYPE6; + classs[ExceptionConstants.TYPES2.length + 2] = ExceptionConstants.TYPE14; + classs[ExceptionConstants.TYPES2.length + 1] = ExceptionConstants.TYPE9; + classs[ExceptionConstants.TYPES2.length] = ExceptionConstants.TYPE3; + return classs; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/IOR.java b/src/main/java/com/allatori/lib/bcel/generic/IOR.java new file mode 100644 index 0000000..c5be43b --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/IOR.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class IOR extends ArithmeticInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitArithmeticInstruction(this); + visitor.visitIOR(this); + } + + public IOR() { + super((short) 128); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/IREM.java b/src/main/java/com/allatori/lib/bcel/generic/IREM.java new file mode 100644 index 0000000..4637918 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/IREM.java @@ -0,0 +1,25 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.ExceptionConstants; + +public class IREM extends ArithmeticInstruction implements ExceptionThrower { + + @Override + public Class[] getExceptions() { + return new Class[] {ExceptionConstants.TYPE18}; + } + + @Override + public void accept(Visitor visitor) { + visitor.visitExceptionThrower(this); + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitArithmeticInstruction(this); + visitor.visitIREM(this); + } + + public IREM() { + super((short) 112); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/IRETURN.java b/src/main/java/com/allatori/lib/bcel/generic/IRETURN.java new file mode 100644 index 0000000..1a50bea --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/IRETURN.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class IRETURN extends ReturnInstruction { + + public IRETURN() { + super((short) 172); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitExceptionThrower(this); + visitor.visitTypedInstruction(this); + visitor.visitStackConsumer(this); + visitor.visitReturnInstruction(this); + visitor.visitIRETURN(this); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/ISHL.java b/src/main/java/com/allatori/lib/bcel/generic/ISHL.java new file mode 100644 index 0000000..2725cf5 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/ISHL.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class ISHL extends ArithmeticInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitArithmeticInstruction(this); + visitor.visitISHL(this); + } + + public ISHL() { + super((short) 120); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/ISHR.java b/src/main/java/com/allatori/lib/bcel/generic/ISHR.java new file mode 100644 index 0000000..2f14dc5 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/ISHR.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class ISHR extends ArithmeticInstruction { + + public ISHR() { + super((short) 122); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitArithmeticInstruction(this); + visitor.visitISHR(this); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/ISTORE.java b/src/main/java/com/allatori/lib/bcel/generic/ISTORE.java new file mode 100644 index 0000000..eed138f --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/ISTORE.java @@ -0,0 +1,18 @@ +package com.allatori.lib.bcel.generic; + +public class ISTORE extends StoreInstruction { + + @Override + public void accept(Visitor visitor) { + super.accept(visitor); + visitor.visitISTORE(this); + } + + public ISTORE() { + super((short) 54, (short) 59); + } + + public ISTORE(int value) { + super((short) 54, (short) 59, value); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/ISUB.java b/src/main/java/com/allatori/lib/bcel/generic/ISUB.java new file mode 100644 index 0000000..62bf1b3 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/ISUB.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class ISUB extends ArithmeticInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitArithmeticInstruction(this); + visitor.visitISUB(this); + } + + public ISUB() { + super((short) 100); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/IUSHR.java b/src/main/java/com/allatori/lib/bcel/generic/IUSHR.java new file mode 100644 index 0000000..5de8804 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/IUSHR.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class IUSHR extends ArithmeticInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitArithmeticInstruction(this); + visitor.visitIUSHR(this); + } + + public IUSHR() { + super((short) 124); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/IXOR.java b/src/main/java/com/allatori/lib/bcel/generic/IXOR.java new file mode 100644 index 0000000..0fed3bd --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/IXOR.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class IXOR extends ArithmeticInstruction { + + public IXOR() { + super((short) 130); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitArithmeticInstruction(this); + visitor.visitIXOR(this); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/IfInstruction.java b/src/main/java/com/allatori/lib/bcel/generic/IfInstruction.java new file mode 100644 index 0000000..d91d94b --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/IfInstruction.java @@ -0,0 +1,12 @@ +package com.allatori.lib.bcel.generic; + +public abstract class IfInstruction extends BranchInstruction implements StackConsumer { + + public IfInstruction() {} + + public abstract IfInstruction negate(); + + public IfInstruction(short value, InstructionHandle instructionHandle) { + super(value, instructionHandle); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/IndexedInstruction.java b/src/main/java/com/allatori/lib/bcel/generic/IndexedInstruction.java new file mode 100644 index 0000000..4307ed1 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/IndexedInstruction.java @@ -0,0 +1,8 @@ +package com.allatori.lib.bcel.generic; + +public interface IndexedInstruction { + + int getIndex(); + + void setIndex(int value); +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/Instruction.java b/src/main/java/com/allatori/lib/bcel/generic/Instruction.java new file mode 100644 index 0000000..79b3591 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/Instruction.java @@ -0,0 +1,671 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.internal.NameSignatureInstructionSupport; +import com.allatori.lib.bcel.Constants; +import com.allatori.lib.bcel.classfile.ConstantPool; +import com.allatori.lib.bcel.util.ByteSequence; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.Serializable; +import java.util.Locale; + +public abstract class Instruction implements Cloneable, Serializable { + + public static InstructionComparator cmp = InstructionComparator.DEFAULT; + + public short length = 1; + + public short opcode = -1; + + public short getOpcode() { + return this.opcode; + } + + public void initFromFile(ByteSequence byteSequence, boolean matches) throws IOException {} + + public void dump(DataOutputStream dataOutputStream) throws IOException { + dataOutputStream.writeByte(this.opcode); + } + + public int produceStack(ConstantPoolGen constantPoolGen) { + return Constants.COUNTS[this.opcode]; + } + + public void setOpcode(short opcode) { + this.opcode = opcode; + } + + public String toString(ConstantPool constantPool) { + return this.toString(false); + } + + public String getText() { + return Constants.TEXTS8[this.opcode]; + } + + public Instruction copy() { + if (InstructionConstants.INSTRUCTIONS[this.getOpcode()] != null) { + return this; + } + try { + return (Instruction) this.clone(); + } catch (CloneNotSupportedException cloneNotSupportedException) { + System.err.println(cloneNotSupportedException); + return (Instruction) (Object) null; + } + } + + public int getLength() { + return this.length; + } + + public Instruction() {} + + public static final String className(short value) { + String text = Constants.TEXTS8[value].toUpperCase(Locale.ENGLISH); + try { + int value2; + char value3 = text.charAt((value2 = text.length()) - 2); + char value4 = text.charAt(value2 - 1); + if (value3 == '_' && value4 >= '0' && value4 <= '5') { + text = text.substring(0, value2 - 2); + } + if (text.equals("ICONST_M1")) { + text = "ICONST"; + } + } catch (StringIndexOutOfBoundsException stringIndexOutOfBoundsException) { + System.err.println(stringIndexOutOfBoundsException); + } + return "org.apache.bcel.generic." + text; + } + + public static InstructionComparator getComparator() { + return cmp; + } + + public String toString(boolean matches) { + return matches + ? ("" + this.getText() + "[" + this.opcode + "](" + this.length + ")") + : this.getText(); + } + + @Override + public boolean equals(Object result) { + return result instanceof Instruction ? cmp.equals(this, (Instruction) result) : false; + } + + public abstract void accept(Visitor visitor); + + public void dispose() {} + + public int consumeStack(ConstantPoolGen constantPoolGen) { + return Constants.COUNTS2[this.opcode]; + } + + public static final Instruction readInstruction(ByteSequence byteSequence) throws IOException { + byte value = 0; + short value2 = (short) byteSequence.readUnsignedByte(); + if (value2 == 196) { + value = 1; + value2 = (short) byteSequence.readUnsignedByte(); + } + if (InstructionConstants.INSTRUCTIONS[value2] != null) { + return InstructionConstants.INSTRUCTIONS[value2]; + } + Instruction instruction; + try { + switch (value2) { + case 0: + instruction = new NOP(); + break; + case 1: + instruction = new ACONST_NULL(); + break; + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + instruction = new ICONST(); + break; + case 9: + case 10: + instruction = new LCONST(); + break; + case 11: + case 12: + case 13: + instruction = new FCONST(); + break; + case 14: + case 15: + instruction = new DCONST(); + break; + case 16: + instruction = new BIPUSH(); + break; + case 17: + instruction = new SIPUSH(); + break; + case 18: + instruction = new LDC(); + break; + case 19: + instruction = new LDC_W(); + break; + case 20: + instruction = new LDC2_W(); + break; + case 21: + instruction = new ILOAD(); + break; + case 22: + instruction = new LLOAD(); + break; + case 23: + instruction = new FLOAD(); + break; + case 24: + instruction = new DLOAD(); + break; + case 25: + instruction = new ALOAD(); + break; + case 26: + case 27: + case 28: + case 29: + instruction = new ILOAD(); + break; + case 30: + case 31: + case 32: + case 33: + instruction = new LLOAD(); + break; + case 34: + case 35: + case 36: + case 37: + instruction = new FLOAD(); + break; + case 38: + case 39: + case 40: + case 41: + instruction = new DLOAD(); + break; + case 42: + case 43: + case 44: + case 45: + instruction = new ALOAD(); + break; + case 46: + instruction = new IALOAD(); + break; + case 47: + instruction = new LALOAD(); + break; + case 48: + instruction = new FALOAD(); + break; + case 49: + instruction = new DALOAD(); + break; + case 50: + instruction = new AALOAD(); + break; + case 51: + instruction = new BALOAD(); + break; + case 52: + instruction = new CALOAD(); + break; + case 53: + instruction = new SALOAD(); + break; + case 54: + instruction = new ISTORE(); + break; + case 55: + instruction = new LSTORE(); + break; + case 56: + instruction = new FSTORE(); + break; + case 57: + instruction = new DSTORE(); + break; + case 58: + instruction = new ASTORE(); + break; + case 59: + case 60: + case 61: + case 62: + instruction = new ISTORE(); + break; + case 63: + case 64: + case 65: + case 66: + instruction = new LSTORE(); + break; + case 67: + case 68: + case 69: + case 70: + instruction = new FSTORE(); + break; + case 71: + case 72: + case 73: + case 74: + instruction = new DSTORE(); + break; + case 75: + case 76: + case 77: + case 78: + instruction = new ASTORE(); + break; + case 79: + instruction = new IASTORE(); + break; + case 80: + instruction = new LASTORE(); + break; + case 81: + instruction = new FASTORE(); + break; + case 82: + instruction = new DASTORE(); + break; + case 83: + instruction = new AASTORE(); + break; + case 84: + instruction = new BASTORE(); + break; + case 85: + instruction = new CASTORE(); + break; + case 86: + instruction = new SASTORE(); + break; + case 87: + instruction = new POP(); + break; + case 88: + instruction = new POP2(); + break; + case 89: + instruction = new DUP(); + break; + case 90: + instruction = new DUP_X1(); + break; + case 91: + instruction = new DUP_X2(); + break; + case 92: + instruction = new DUP2(); + break; + case 93: + instruction = new DUP2_X1(); + break; + case 94: + instruction = new DUP2_X2(); + break; + case 95: + instruction = new SWAP(); + break; + case 96: + instruction = new IADD(); + break; + case 97: + instruction = new LADD(); + break; + case 98: + instruction = new FADD(); + break; + case 99: + instruction = new DADD(); + break; + case 100: + instruction = new ISUB(); + break; + case 101: + instruction = new LSUB(); + break; + case 102: + instruction = new FSUB(); + break; + case 103: + instruction = new DSUB(); + break; + case 104: + instruction = new IMUL(); + break; + case 105: + instruction = new LMUL(); + break; + case 106: + instruction = new FMUL(); + break; + case 107: + instruction = new DMUL(); + break; + case 108: + instruction = new IDIV(); + break; + case 109: + instruction = new LDIV(); + break; + case 110: + instruction = new FDIV(); + break; + case 111: + instruction = new DDIV(); + break; + case 112: + instruction = new IREM(); + break; + case 113: + instruction = new LREM(); + break; + case 114: + instruction = new FREM(); + break; + case 115: + instruction = new DREM(); + break; + case 116: + instruction = new INEG(); + break; + case 117: + instruction = new LNEG(); + break; + case 118: + instruction = new FNEG(); + break; + case 119: + instruction = new DNEG(); + break; + case 120: + instruction = new ISHL(); + break; + case 121: + instruction = new LSHL(); + break; + case 122: + instruction = new ISHR(); + break; + case 123: + instruction = new LSHR(); + break; + case 124: + instruction = new IUSHR(); + break; + case 125: + instruction = new LUSHR(); + break; + case 126: + instruction = new IAND(); + break; + case 127: + instruction = new LAND(); + break; + case 128: + instruction = new IOR(); + break; + case 129: + instruction = new LOR(); + break; + case 130: + instruction = new IXOR(); + break; + case 131: + instruction = new LXOR(); + break; + case 132: + instruction = new IINC(); + break; + case 133: + instruction = new I2L(); + break; + case 134: + instruction = new I2F(); + break; + case 135: + instruction = new I2D(); + break; + case 136: + instruction = new L2I(); + break; + case 137: + instruction = new L2F(); + break; + case 138: + instruction = new L2D(); + break; + case 139: + instruction = new F2I(); + break; + case 140: + instruction = new F2L(); + break; + case 141: + instruction = new F2D(); + break; + case 142: + instruction = new D2I(); + break; + case 143: + instruction = new D2L(); + break; + case 144: + instruction = new D2F(); + break; + case 145: + instruction = new I2B(); + break; + case 146: + instruction = new I2C(); + break; + case 147: + instruction = new I2S(); + break; + case 148: + instruction = new LCMP(); + break; + case 149: + instruction = new FCMPL(); + break; + case 150: + instruction = new FCMPG(); + break; + case 151: + instruction = new DCMPL(); + break; + case 152: + instruction = new DCMPG(); + break; + case 153: + instruction = new IFEQ(); + break; + case 154: + instruction = new IFNE(); + break; + case 155: + instruction = new IFLT(); + break; + case 156: + instruction = new IFGE(); + break; + case 157: + instruction = new IFGT(); + break; + case 158: + instruction = new IFLE(); + break; + case 159: + instruction = new IF_ICMPEQ(); + break; + case 160: + instruction = new IF_ICMPNE(); + break; + case 161: + instruction = new IF_ICMPLT(); + break; + case 162: + instruction = new IF_ICMPGE(); + break; + case 163: + instruction = new IF_ICMPGT(); + break; + case 164: + instruction = new IF_ICMPLE(); + break; + case 165: + instruction = new IF_ACMPEQ(); + break; + case 166: + instruction = new IF_ACMPNE(); + break; + case 167: + instruction = new GOTO(); + break; + case 168: + instruction = new JSR(); + break; + case 169: + instruction = new RET(); + break; + case 170: + instruction = new TABLESWITCH(); + break; + case 171: + instruction = new LOOKUPSWITCH(); + break; + case 172: + instruction = new IRETURN(); + break; + case 173: + instruction = new LRETURN(); + break; + case 174: + instruction = new FRETURN(); + break; + case 175: + instruction = new DRETURN(); + break; + case 176: + instruction = new ARETURN(); + break; + case 177: + instruction = new RETURN(); + break; + case 178: + instruction = new GETSTATIC(); + break; + case 179: + instruction = new PUTSTATIC(); + break; + case 180: + instruction = new GETFIELD(); + break; + case 181: + instruction = new PUTFIELD(); + break; + case 182: + instruction = new INVOKEVIRTUAL(); + break; + case 183: + instruction = new INVOKESPECIAL(); + break; + case 184: + instruction = new INVOKESTATIC(); + break; + case 185: + instruction = new INVOKEINTERFACE(); + break; + case 186: + instruction = new NameSignatureInstructionSupport(); + break; + case 187: + instruction = new NEW(); + break; + case 188: + instruction = new NEWARRAY(); + break; + case 189: + instruction = new ANEWARRAY(); + break; + case 190: + instruction = new ARRAYLENGTH(); + break; + case 191: + instruction = new ATHROW(); + break; + case 192: + instruction = new CHECKCAST(); + break; + case 193: + instruction = new INSTANCEOF(); + break; + case 194: + instruction = new MONITORENTER(); + break; + case 195: + instruction = new MONITOREXIT(); + break; + case 196: + default: + throw new ClassGenException("Illegal opcode detected"); + case 197: + instruction = new MULTIANEWARRAY(); + break; + case 198: + instruction = new IFNULL(); + break; + case 199: + instruction = new IFNONNULL(); + break; + case 200: + instruction = new GOTO_W(); + break; + case 201: + instruction = new JSR_W(); + } + } catch (ClassGenException classGenException) { + throw classGenException; + } catch (Exception exception) { + throw new ClassGenException(exception.toString()); + } + if (value != 0 + && !(instruction instanceof LocalVariableInstruction) + && !(instruction instanceof IINC) + && !(instruction instanceof RET)) { + throw new ClassGenException(("Illegal opcode after wide: " + value2)); + } + instruction.setOpcode(value2); + instruction.initFromFile(byteSequence, value != 0); + return instruction; + } + + public Instruction(short opcode, short length) { + super(); + this.length = 1; + this.opcode = -1; + this.length = length; + this.opcode = opcode; + } + + public static void setComparator(InstructionComparator instructionComparator) { + cmp = instructionComparator; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/InstructionComparator$1.java b/src/main/java/com/allatori/lib/bcel/generic/InstructionComparator$1.java new file mode 100644 index 0000000..e845248 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/InstructionComparator$1.java @@ -0,0 +1,50 @@ +package com.allatori.lib.bcel.generic; + +public class InstructionComparator$1 implements InstructionComparator { + + @Override + public boolean equals(Instruction instruction, Instruction instruction2) { + if (instruction.opcode == instruction2.opcode) { + if (!(instruction instanceof Select)) { + if (instruction instanceof BranchInstruction) { + if (((BranchInstruction) instruction).target + == ((BranchInstruction) instruction2).target) { + return true; + } + return false; + } + if (instruction instanceof ConstantPushInstruction) { + return ((ConstantPushInstruction) instruction) + .getValue() + .equals(((ConstantPushInstruction) instruction2).getValue()); + } + if (instruction instanceof IndexedInstruction) { + if (((IndexedInstruction) instruction).getIndex() + == ((IndexedInstruction) instruction2).getIndex()) { + return true; + } + return false; + } + if (instruction instanceof NEWARRAY) { + if (((NEWARRAY) instruction).getTypecode() == ((NEWARRAY) instruction2).getTypecode()) { + return true; + } + return false; + } + return true; + } + InstructionHandle[] targets = ((Select) instruction).getTargets(); + InstructionHandle[] targets2 = ((Select) instruction2).getTargets(); + if (targets.length == targets2.length) { + int value; + for (int value2 = value = 0; value2 < targets.length; value2 = ++value) { + if (targets[value] != targets2[value]) { + return false; + } + } + return true; + } + } + return false; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/InstructionComparator.java b/src/main/java/com/allatori/lib/bcel/generic/InstructionComparator.java new file mode 100644 index 0000000..ab97adf --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/InstructionComparator.java @@ -0,0 +1,8 @@ +package com.allatori.lib.bcel.generic; + +public interface InstructionComparator { + + InstructionComparator DEFAULT = new InstructionComparator$1(); + + boolean equals(Instruction instruction, Instruction instruction2); +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/InstructionConstants$Clinit.java b/src/main/java/com/allatori/lib/bcel/generic/InstructionConstants$Clinit.java new file mode 100644 index 0000000..a05d64c --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/InstructionConstants$Clinit.java @@ -0,0 +1,114 @@ +package com.allatori.lib.bcel.generic; + +public class InstructionConstants$Clinit { + + public InstructionConstants$Clinit() { + InstructionConstants.INSTRUCTIONS[0] = InstructionConstants.NOP; + InstructionConstants.INSTRUCTIONS[1] = InstructionConstants.ACONST_NULL; + InstructionConstants.INSTRUCTIONS[2] = InstructionConstants.ICONST_M1; + InstructionConstants.INSTRUCTIONS[3] = InstructionConstants.ICONST_0; + InstructionConstants.INSTRUCTIONS[4] = InstructionConstants.ICONST_1; + InstructionConstants.INSTRUCTIONS[5] = InstructionConstants.ICONST_2; + InstructionConstants.INSTRUCTIONS[6] = InstructionConstants.ICONST_3; + InstructionConstants.INSTRUCTIONS[7] = InstructionConstants.ICONST_4; + InstructionConstants.INSTRUCTIONS[8] = InstructionConstants.ICONST_5; + InstructionConstants.INSTRUCTIONS[9] = InstructionConstants.LCONST_0; + InstructionConstants.INSTRUCTIONS[10] = InstructionConstants.LCONST_1; + InstructionConstants.INSTRUCTIONS[11] = InstructionConstants.FCONST_0; + InstructionConstants.INSTRUCTIONS[12] = InstructionConstants.FCONST_1; + InstructionConstants.INSTRUCTIONS[13] = InstructionConstants.FCONST_2; + InstructionConstants.INSTRUCTIONS[14] = InstructionConstants.DCONST_0; + InstructionConstants.INSTRUCTIONS[15] = InstructionConstants.DCONST_1; + InstructionConstants.INSTRUCTIONS[46] = InstructionConstants.IALOAD; + InstructionConstants.INSTRUCTIONS[47] = InstructionConstants.LALOAD; + InstructionConstants.INSTRUCTIONS[48] = InstructionConstants.FALOAD; + InstructionConstants.INSTRUCTIONS[49] = InstructionConstants.DALOAD; + InstructionConstants.INSTRUCTIONS[50] = InstructionConstants.AALOAD; + InstructionConstants.INSTRUCTIONS[51] = InstructionConstants.BALOAD; + InstructionConstants.INSTRUCTIONS[52] = InstructionConstants.CALOAD; + InstructionConstants.INSTRUCTIONS[53] = InstructionConstants.SALOAD; + InstructionConstants.INSTRUCTIONS[79] = InstructionConstants.IASTORE; + InstructionConstants.INSTRUCTIONS[80] = InstructionConstants.LASTORE; + InstructionConstants.INSTRUCTIONS[81] = InstructionConstants.FASTORE; + InstructionConstants.INSTRUCTIONS[82] = InstructionConstants.DASTORE; + InstructionConstants.INSTRUCTIONS[83] = InstructionConstants.AASTORE; + InstructionConstants.INSTRUCTIONS[84] = InstructionConstants.BASTORE; + InstructionConstants.INSTRUCTIONS[85] = InstructionConstants.CASTORE; + InstructionConstants.INSTRUCTIONS[86] = InstructionConstants.SASTORE; + InstructionConstants.INSTRUCTIONS[87] = InstructionConstants.POP; + InstructionConstants.INSTRUCTIONS[88] = InstructionConstants.POP2; + InstructionConstants.INSTRUCTIONS[89] = InstructionConstants.DUP; + InstructionConstants.INSTRUCTIONS[90] = InstructionConstants.DUP_X1; + InstructionConstants.INSTRUCTIONS[91] = InstructionConstants.DUP_X2; + InstructionConstants.INSTRUCTIONS[92] = InstructionConstants.DUP2; + InstructionConstants.INSTRUCTIONS[93] = InstructionConstants.DUP2_X1; + InstructionConstants.INSTRUCTIONS[94] = InstructionConstants.DUP2_X2; + InstructionConstants.INSTRUCTIONS[95] = InstructionConstants.SWAP; + InstructionConstants.INSTRUCTIONS[96] = InstructionConstants.IADD; + InstructionConstants.INSTRUCTIONS[97] = InstructionConstants.LADD; + InstructionConstants.INSTRUCTIONS[98] = InstructionConstants.FADD; + InstructionConstants.INSTRUCTIONS[99] = InstructionConstants.DADD; + InstructionConstants.INSTRUCTIONS[100] = InstructionConstants.ISUB; + InstructionConstants.INSTRUCTIONS[101] = InstructionConstants.LSUB; + InstructionConstants.INSTRUCTIONS[102] = InstructionConstants.FSUB; + InstructionConstants.INSTRUCTIONS[103] = InstructionConstants.DSUB; + InstructionConstants.INSTRUCTIONS[104] = InstructionConstants.IMUL; + InstructionConstants.INSTRUCTIONS[105] = InstructionConstants.LMUL; + InstructionConstants.INSTRUCTIONS[106] = InstructionConstants.FMUL; + InstructionConstants.INSTRUCTIONS[107] = InstructionConstants.DMUL; + InstructionConstants.INSTRUCTIONS[108] = InstructionConstants.IDIV; + InstructionConstants.INSTRUCTIONS[109] = InstructionConstants.LDIV; + InstructionConstants.INSTRUCTIONS[110] = InstructionConstants.FDIV; + InstructionConstants.INSTRUCTIONS[111] = InstructionConstants.DDIV; + InstructionConstants.INSTRUCTIONS[112] = InstructionConstants.IREM; + InstructionConstants.INSTRUCTIONS[113] = InstructionConstants.LREM; + InstructionConstants.INSTRUCTIONS[114] = InstructionConstants.FREM; + InstructionConstants.INSTRUCTIONS[115] = InstructionConstants.DREM; + InstructionConstants.INSTRUCTIONS[116] = InstructionConstants.INEG; + InstructionConstants.INSTRUCTIONS[117] = InstructionConstants.LNEG; + InstructionConstants.INSTRUCTIONS[118] = InstructionConstants.FNEG; + InstructionConstants.INSTRUCTIONS[119] = InstructionConstants.DNEG; + InstructionConstants.INSTRUCTIONS[120] = InstructionConstants.ISHL; + InstructionConstants.INSTRUCTIONS[121] = InstructionConstants.LSHL; + InstructionConstants.INSTRUCTIONS[122] = InstructionConstants.ISHR; + InstructionConstants.INSTRUCTIONS[123] = InstructionConstants.LSHR; + InstructionConstants.INSTRUCTIONS[124] = InstructionConstants.IUSHR; + InstructionConstants.INSTRUCTIONS[125] = InstructionConstants.LUSHR; + InstructionConstants.INSTRUCTIONS[126] = InstructionConstants.IAND; + InstructionConstants.INSTRUCTIONS[127] = InstructionConstants.LAND; + InstructionConstants.INSTRUCTIONS[128] = InstructionConstants.IOR; + InstructionConstants.INSTRUCTIONS[129] = InstructionConstants.LOR; + InstructionConstants.INSTRUCTIONS[130] = InstructionConstants.IXOR; + InstructionConstants.INSTRUCTIONS[131] = InstructionConstants.LXOR; + InstructionConstants.INSTRUCTIONS[133] = InstructionConstants.I2L; + InstructionConstants.INSTRUCTIONS[134] = InstructionConstants.I2F; + InstructionConstants.INSTRUCTIONS[135] = InstructionConstants.I2D; + InstructionConstants.INSTRUCTIONS[136] = InstructionConstants.L2I; + InstructionConstants.INSTRUCTIONS[137] = InstructionConstants.L2F; + InstructionConstants.INSTRUCTIONS[138] = InstructionConstants.L2D; + InstructionConstants.INSTRUCTIONS[139] = InstructionConstants.F2I; + InstructionConstants.INSTRUCTIONS[140] = InstructionConstants.F2L; + InstructionConstants.INSTRUCTIONS[141] = InstructionConstants.F2D; + InstructionConstants.INSTRUCTIONS[142] = InstructionConstants.D2I; + InstructionConstants.INSTRUCTIONS[143] = InstructionConstants.D2L; + InstructionConstants.INSTRUCTIONS[144] = InstructionConstants.D2F; + InstructionConstants.INSTRUCTIONS[145] = InstructionConstants.I2B; + InstructionConstants.INSTRUCTIONS[146] = InstructionConstants.I2C; + InstructionConstants.INSTRUCTIONS[147] = InstructionConstants.I2S; + InstructionConstants.INSTRUCTIONS[148] = InstructionConstants.LCMP; + InstructionConstants.INSTRUCTIONS[149] = InstructionConstants.FCMPL; + InstructionConstants.INSTRUCTIONS[150] = InstructionConstants.FCMPG; + InstructionConstants.INSTRUCTIONS[151] = InstructionConstants.DCMPL; + InstructionConstants.INSTRUCTIONS[152] = InstructionConstants.DCMPG; + InstructionConstants.INSTRUCTIONS[172] = InstructionConstants.IRETURN; + InstructionConstants.INSTRUCTIONS[173] = InstructionConstants.LRETURN; + InstructionConstants.INSTRUCTIONS[174] = InstructionConstants.FRETURN; + InstructionConstants.INSTRUCTIONS[175] = InstructionConstants.DRETURN; + InstructionConstants.INSTRUCTIONS[176] = InstructionConstants.ARETURN; + InstructionConstants.INSTRUCTIONS[177] = InstructionConstants.RETURN; + InstructionConstants.INSTRUCTIONS[190] = InstructionConstants.ARRAYLENGTH; + InstructionConstants.INSTRUCTIONS[191] = InstructionConstants.ATHROW; + InstructionConstants.INSTRUCTIONS[194] = InstructionConstants.MONITORENTER; + InstructionConstants.INSTRUCTIONS[195] = InstructionConstants.MONITOREXIT; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/InstructionConstants.java b/src/main/java/com/allatori/lib/bcel/generic/InstructionConstants.java new file mode 100644 index 0000000..7f89b57 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/InstructionConstants.java @@ -0,0 +1,248 @@ +package com.allatori.lib.bcel.generic; + +public interface InstructionConstants { + + Instruction NOP = new NOP(); + + Instruction ACONST_NULL = new ACONST_NULL(); + + Instruction ICONST_M1 = new ICONST(-1); + + Instruction ICONST_0 = new ICONST(0); + + Instruction ICONST_1 = new ICONST(1); + + Instruction ICONST_2 = new ICONST(2); + + Instruction ICONST_3 = new ICONST(3); + + Instruction ICONST_4 = new ICONST(4); + + Instruction ICONST_5 = new ICONST(5); + + Instruction LCONST_0 = new LCONST(0L); + + Instruction LCONST_1 = new LCONST(1L); + + Instruction FCONST_0 = new FCONST(0.0F); + + Instruction FCONST_1 = new FCONST(1.0F); + + Instruction FCONST_2 = new FCONST(2.0F); + + Instruction DCONST_0 = new DCONST(0.0); + + Instruction DCONST_1 = new DCONST(1.0); + + ArrayInstruction IALOAD = new IALOAD(); + + ArrayInstruction LALOAD = new LALOAD(); + + ArrayInstruction FALOAD = new FALOAD(); + + ArrayInstruction DALOAD = new DALOAD(); + + ArrayInstruction AALOAD = new AALOAD(); + + ArrayInstruction BALOAD = new BALOAD(); + + ArrayInstruction CALOAD = new CALOAD(); + + ArrayInstruction SALOAD = new SALOAD(); + + ArrayInstruction IASTORE = new IASTORE(); + + ArrayInstruction LASTORE = new LASTORE(); + + ArrayInstruction FASTORE = new FASTORE(); + + ArrayInstruction DASTORE = new DASTORE(); + + ArrayInstruction AASTORE = new AASTORE(); + + ArrayInstruction BASTORE = new BASTORE(); + + ArrayInstruction CASTORE = new CASTORE(); + + ArrayInstruction SASTORE = new SASTORE(); + + StackInstruction POP = new POP(); + + StackInstruction POP2 = new POP2(); + + StackInstruction DUP = new DUP(); + + StackInstruction DUP_X1 = new DUP_X1(); + + StackInstruction DUP_X2 = new DUP_X2(); + + StackInstruction DUP2 = new DUP2(); + + StackInstruction DUP2_X1 = new DUP2_X1(); + + StackInstruction DUP2_X2 = new DUP2_X2(); + + StackInstruction SWAP = new SWAP(); + + ArithmeticInstruction IADD = new IADD(); + + ArithmeticInstruction LADD = new LADD(); + + ArithmeticInstruction FADD = new FADD(); + + ArithmeticInstruction DADD = new DADD(); + + ArithmeticInstruction ISUB = new ISUB(); + + ArithmeticInstruction LSUB = new LSUB(); + + ArithmeticInstruction FSUB = new FSUB(); + + ArithmeticInstruction DSUB = new DSUB(); + + ArithmeticInstruction IMUL = new IMUL(); + + ArithmeticInstruction LMUL = new LMUL(); + + ArithmeticInstruction FMUL = new FMUL(); + + ArithmeticInstruction DMUL = new DMUL(); + + ArithmeticInstruction IDIV = new IDIV(); + + ArithmeticInstruction LDIV = new LDIV(); + + ArithmeticInstruction FDIV = new FDIV(); + + ArithmeticInstruction DDIV = new DDIV(); + + ArithmeticInstruction IREM = new IREM(); + + ArithmeticInstruction LREM = new LREM(); + + ArithmeticInstruction FREM = new FREM(); + + ArithmeticInstruction DREM = new DREM(); + + ArithmeticInstruction INEG = new INEG(); + + ArithmeticInstruction LNEG = new LNEG(); + + ArithmeticInstruction FNEG = new FNEG(); + + ArithmeticInstruction DNEG = new DNEG(); + + ArithmeticInstruction ISHL = new ISHL(); + + ArithmeticInstruction LSHL = new LSHL(); + + ArithmeticInstruction ISHR = new ISHR(); + + ArithmeticInstruction LSHR = new LSHR(); + + ArithmeticInstruction IUSHR = new IUSHR(); + + ArithmeticInstruction LUSHR = new LUSHR(); + + ArithmeticInstruction IAND = new IAND(); + + ArithmeticInstruction LAND = new LAND(); + + ArithmeticInstruction IOR = new IOR(); + + ArithmeticInstruction LOR = new LOR(); + + ArithmeticInstruction IXOR = new IXOR(); + + ArithmeticInstruction LXOR = new LXOR(); + + ConversionInstruction I2L = new I2L(); + + ConversionInstruction I2F = new I2F(); + + ConversionInstruction I2D = new I2D(); + + ConversionInstruction L2I = new L2I(); + + ConversionInstruction L2F = new L2F(); + + ConversionInstruction L2D = new L2D(); + + ConversionInstruction F2I = new F2I(); + + ConversionInstruction F2L = new F2L(); + + ConversionInstruction F2D = new F2D(); + + ConversionInstruction D2I = new D2I(); + + ConversionInstruction D2L = new D2L(); + + ConversionInstruction D2F = new D2F(); + + ConversionInstruction I2B = new I2B(); + + ConversionInstruction I2C = new I2C(); + + ConversionInstruction I2S = new I2S(); + + Instruction LCMP = new LCMP(); + + Instruction FCMPL = new FCMPL(); + + Instruction FCMPG = new FCMPG(); + + Instruction DCMPL = new DCMPL(); + + Instruction DCMPG = new DCMPG(); + + ReturnInstruction IRETURN = new IRETURN(); + + ReturnInstruction LRETURN = new LRETURN(); + + ReturnInstruction FRETURN = new FRETURN(); + + ReturnInstruction DRETURN = new DRETURN(); + + ReturnInstruction ARETURN = new ARETURN(); + + ReturnInstruction RETURN = new RETURN(); + + Instruction ARRAYLENGTH = new ARRAYLENGTH(); + + Instruction ATHROW = new ATHROW(); + + Instruction MONITORENTER = new MONITORENTER(); + + Instruction MONITOREXIT = new MONITOREXIT(); + + LocalVariableInstruction ALOAD_0 = new ALOAD(0); + + LocalVariableInstruction LOCAL_VARIABLE_INSTRUCTION6 = ALOAD_0; + + LocalVariableInstruction ALOAD_1 = new ALOAD(1); + + LocalVariableInstruction ALOAD_2 = new ALOAD(2); + + LocalVariableInstruction ILOAD_0 = new ILOAD(0); + + LocalVariableInstruction ILOAD_1 = new ILOAD(1); + + LocalVariableInstruction ILOAD_2 = new ILOAD(2); + + LocalVariableInstruction ASTORE_0 = new ASTORE(0); + + LocalVariableInstruction ASTORE_1 = new ASTORE(1); + + LocalVariableInstruction ASTORE_2 = new ASTORE(2); + + LocalVariableInstruction ISTORE_0 = new ISTORE(0); + + LocalVariableInstruction ISTORE_1 = new ISTORE(1); + + LocalVariableInstruction ISTORE_2 = new ISTORE(2); + + Instruction[] INSTRUCTIONS = new Instruction[256]; + + InstructionConstants$Clinit bla = new InstructionConstants$Clinit(); +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/InstructionFactory$MethodObject.java b/src/main/java/com/allatori/lib/bcel/generic/InstructionFactory$MethodObject.java new file mode 100644 index 0000000..32c72d9 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/InstructionFactory$MethodObject.java @@ -0,0 +1,24 @@ +package com.allatori.lib.bcel.generic; + +public class InstructionFactory$MethodObject { + + public String name; + + public int access; + + public String class_name; + + public Type[] arg_types; + + public Type result_type; + + public InstructionFactory$MethodObject( + String class_name, String name, Type type, Type[] types, int access) { + super(); + this.class_name = class_name; + this.name = name; + this.result_type = type; + this.arg_types = types; + this.access = access; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/InstructionFactory.java b/src/main/java/com/allatori/lib/bcel/generic/InstructionFactory.java new file mode 100644 index 0000000..6ff3ce2 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/InstructionFactory.java @@ -0,0 +1,634 @@ +package com.allatori.lib.bcel.generic; + +import java.io.Serializable; + +public class InstructionFactory implements InstructionConstants, Serializable { + + public ConstantPoolGen cp; + + public static final String[] short_names = new String[] {"C", "F", "D", "B", "S", "I", "L"}; + + public ClassGen cg; + + public static InstructionFactory$MethodObject[] append_mos; + + public INSTANCEOF createInstanceOf(ReferenceType referenceType) { + return referenceType instanceof ArrayType + ? new INSTANCEOF(this.cp.addArrayClass((ArrayType) referenceType)) + : new INSTANCEOF(this.cp.addClass((ObjectType) referenceType)); + } + + public GETSTATIC createGetStatic(String text, String text2, Type type) { + return new GETSTATIC(this.cp.addFieldref(text, text2, type.getSignature())); + } + + public InstructionFactory(ClassGen classGen, ConstantPoolGen constantPoolGen) { + super(); + this.cg = classGen; + this.cp = constantPoolGen; + } + + public InstructionFactory(ClassGen classGen) { + this(classGen, classGen.getConstantPool()); + } + + public static final ArithmeticInstruction createArithmeticInstruction(char value, String text) { + switch (value) { + case '%': + return LREM; + case '&': + return LAND; + case '*': + return LMUL; + case '+': + return LADD; + case '-': + return LSUB; + case '/': + return LDIV; + case '<': + return LSHL; + case '>': + if (text.equals(">>>")) { + return LUSHR; + } + return LSHR; + case '^': + return LXOR; + case '|': + return LOR; + default: + throw new RuntimeException(("Invalid operand " + text)); + } + } + + public PUTSTATIC createPutStatic(String text, String text2, Type type) { + return new PUTSTATIC(this.cp.addFieldref(text, text2, type.getSignature())); + } + + public static LocalVariableInstruction createLocalVariableInstruction(Type type, int value) { + switch (type.getType()) { + case 4: + case 5: + case 8: + case 9: + case 10: + return new ISTORE(value); + case 6: + return new FSTORE(value); + case 7: + return new DSTORE(value); + case 11: + return new LSTORE(value); + case 12: + default: + throw new RuntimeException(("Invalid type " + type)); + case 13: + case 14: + return new ASTORE(value); + } + } + + public static ArrayInstruction createArrayInstruction(Type type) { + switch (type.getType()) { + case 4: + case 8: + return BASTORE; + case 5: + return CASTORE; + case 6: + return FASTORE; + case 7: + return DASTORE; + case 9: + return SASTORE; + case 10: + return IASTORE; + case 11: + return LASTORE; + case 12: + default: + throw new RuntimeException(("Invalid type " + type)); + case 13: + case 14: + return AASTORE; + } + } + + public void setClassGen(ClassGen classGen) { + this.cg = classGen; + } + + public static StackInstruction getStackInstruction(int value) { + return value == 2 ? DUP2_X2 : DUP_X2; + } + + static { + InstructionFactory$MethodObject[] instructionFactory$MethodObjects = + new InstructionFactory$MethodObject[12]; + instructionFactory$MethodObjects[0] = + new InstructionFactory$MethodObject( + "java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] {Type.STRING}, 1); + instructionFactory$MethodObjects[1] = + new InstructionFactory$MethodObject( + "java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] {Type.OBJECT}, 1); + instructionFactory$MethodObjects[2] = null; + instructionFactory$MethodObjects[3] = null; + instructionFactory$MethodObjects[4] = + new InstructionFactory$MethodObject( + "java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] {Type.BOOLEAN}, 1); + instructionFactory$MethodObjects[5] = + new InstructionFactory$MethodObject( + "java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] {Type.CHAR}, 1); + instructionFactory$MethodObjects[6] = + new InstructionFactory$MethodObject( + "java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] {Type.FLOAT}, 1); + instructionFactory$MethodObjects[7] = + new InstructionFactory$MethodObject( + "java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] {Type.DOUBLE}, 1); + instructionFactory$MethodObjects[8] = + new InstructionFactory$MethodObject( + "java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] {Type.INT}, 1); + instructionFactory$MethodObjects[9] = + new InstructionFactory$MethodObject( + "java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] {Type.INT}, 1); + instructionFactory$MethodObjects[10] = + new InstructionFactory$MethodObject( + "java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] {Type.INT}, 1); + instructionFactory$MethodObjects[11] = + new InstructionFactory$MethodObject( + "java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] {Type.LONG}, 1); + append_mos = instructionFactory$MethodObjects; + } + + public static StackInstruction getStackInstruction2(int value) { + return value == 2 ? DUP2 : DUP; + } + + public ConstantPoolGen getConstantPool() { + return this.cp; + } + + public CHECKCAST createCheckCast(ReferenceType referenceType) { + return referenceType instanceof ArrayType + ? new CHECKCAST(this.cp.addArrayClass((ArrayType) referenceType)) + : new CHECKCAST(this.cp.addClass((ObjectType) referenceType)); + } + + public static StackInstruction getStackInstruction3(int value) { + return value == 2 ? POP2 : POP; + } + + public PUTFIELD createPutField(String text, String text2, Type type) { + return new PUTFIELD(this.cp.addFieldref(text, text2, type.getSignature())); + } + + public static StackInstruction getStackInstruction4(int value) { + return value == 2 ? DUP2_X1 : DUP_X1; + } + + public Instruction createAppend(Type type) { + byte type2 = type.getType(); + if (isString(type)) { + return this.createInvoke(append_mos[0], (short) 182); + } + switch (type2) { + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + return this.createInvoke(append_mos[type2], (short) 182); + case 12: + default: + throw new RuntimeException(("Oops: No append for this type? " + type)); + case 13: + case 14: + return this.createInvoke(append_mos[1], (short) 182); + } + } + + public void setConstantPool(ConstantPoolGen constantPoolGen) { + this.cp = constantPoolGen; + } + + public GETFIELD createGetField(String text, String text2, Type type) { + return new GETFIELD(this.cp.addFieldref(text, text2, type.getSignature())); + } + + public InvokeInstruction createInvoke( + InstructionFactory$MethodObject instructionFactory$MethodObject, short value) { + return this.createInvoke( + instructionFactory$MethodObject.class_name, + instructionFactory$MethodObject.name, + instructionFactory$MethodObject.result_type, + instructionFactory$MethodObject.arg_types, + value); + } + + public static final boolean isString(Type type) { + return type instanceof ObjectType + && ((ObjectType) type).getClassName().equals("java.lang.String"); + } + + public static LocalVariableInstruction createLocalVariableInstruction2(Type type, int value) { + switch (type.getType()) { + case 4: + case 5: + case 8: + case 9: + case 10: + return new ILOAD(value); + case 6: + return new FLOAD(value); + case 7: + return new DLOAD(value); + case 11: + return new LLOAD(value); + case 12: + default: + throw new RuntimeException(("Invalid type " + type)); + case 13: + case 14: + return new ALOAD(value); + } + } + + public static ArrayInstruction createArrayInstruction2(Type type) { + switch (type.getType()) { + case 4: + case 8: + return BALOAD; + case 5: + return CALOAD; + case 6: + return FALOAD; + case 7: + return DALOAD; + case 9: + return SALOAD; + case 10: + return IALOAD; + case 11: + return LALOAD; + case 12: + default: + throw new RuntimeException(("Invalid type " + type)); + case 13: + case 14: + return AALOAD; + } + } + + public FieldInstruction createFieldAccess(String text, String text2, Type type, short value) { + String signature = type.getSignature(); + int value2 = this.cp.addFieldref(text, text2, signature); + switch (value) { + case 178: + return new GETSTATIC(value2); + case 179: + return new PUTSTATIC(value2); + case 180: + return new GETFIELD(value2); + case 181: + return new PUTFIELD(value2); + default: + throw new RuntimeException(("Oops: Unknown getfield kind:" + value)); + } + } + + public static BranchInstruction createBranchInstruction( + short value, InstructionHandle instructionHandle) { + switch (value) { + case 153: + return new IFEQ(instructionHandle); + case 154: + return new IFNE(instructionHandle); + case 155: + return new IFLT(instructionHandle); + case 156: + return new IFGE(instructionHandle); + case 157: + return new IFGT(instructionHandle); + case 158: + return new IFLE(instructionHandle); + case 159: + return new IF_ICMPEQ(instructionHandle); + case 160: + return new IF_ICMPNE(instructionHandle); + case 161: + return new IF_ICMPLT(instructionHandle); + case 162: + return new IF_ICMPGE(instructionHandle); + case 163: + return new IF_ICMPGT(instructionHandle); + case 164: + return new IF_ICMPLE(instructionHandle); + case 165: + return new IF_ACMPEQ(instructionHandle); + case 166: + return new IF_ACMPNE(instructionHandle); + case 167: + return new GOTO(instructionHandle); + case 168: + return new JSR(instructionHandle); + case 169: + case 170: + case 171: + case 172: + case 173: + case 174: + case 175: + case 176: + case 177: + case 178: + case 179: + case 180: + case 181: + case 182: + case 183: + case 184: + case 185: + case 186: + case 187: + case 188: + case 189: + case 190: + case 191: + case 192: + case 193: + case 194: + case 195: + case 196: + case 197: + default: + throw new RuntimeException(("Invalid opcode: " + value)); + case 198: + return new IFNULL(instructionHandle); + case 199: + return new IFNONNULL(instructionHandle); + case 200: + return new GOTO_W(instructionHandle); + case 201: + return new JSR_W(instructionHandle); + } + } + + public Instruction createNewArray(Type type, short value) { + if (value == 1) { + if (type instanceof ObjectType) { + return new ANEWARRAY(this.cp.addClass((ObjectType) type)); + } else { + return type instanceof ArrayType + ? new ANEWARRAY(this.cp.addArrayClass((ArrayType) type)) + : new NEWARRAY(((BasicType) type).getType()); + } + } else { + ArrayType arrayType; + if (type instanceof ArrayType) { + arrayType = (ArrayType) type; + } else { + arrayType = new ArrayType(type, value); + } + return new MULTIANEWARRAY(this.cp.addArrayClass(arrayType), value); + } + } + + public NEW createNew(ObjectType objectType) { + return new NEW(this.cp.addClass(objectType)); + } + + public Instruction createCast(Type type, Type type2) { + if (type instanceof BasicType && type2 instanceof BasicType) { + byte type3 = type2.getType(); + byte type4 = type.getType(); + if (type3 == 11 && (type4 == 5 || type4 == 8 || type4 == 9)) { + type4 = 10; + } + String text = + "org.apache.bcel.generic." + short_names[type4 - 5] + "2" + short_names[type3 - 5]; + try { + return (Instruction) Class.forName(text).newInstance(); + } catch (Exception exception) { + throw new RuntimeException(("Could not find instruction: " + text)); + } + } else if (!(type instanceof ReferenceType) || !(type2 instanceof ReferenceType)) { + throw new RuntimeException(("Can not cast " + type + " to " + type2)); + } else { + return type2 instanceof ArrayType + ? new CHECKCAST(this.cp.addArrayClass((ArrayType) type2)) + : new CHECKCAST(this.cp.addClass(((ObjectType) type2).getClassName())); + } + } + + public static ArithmeticInstruction createBinaryOperation(String text, Type type) { + char value = text.toCharArray()[0]; + switch (type.getType()) { + case 5: + case 8: + case 9: + case 10: + return createArithmeticInstruction2(value, text); + case 6: + return createArithmeticInstruction(value); + case 7: + return createArithmeticInstruction2(value); + case 11: + return createArithmeticInstruction(value, text); + default: + throw new RuntimeException(("Invalid type " + type)); + } + } + + public ClassGen getClassGen() { + return this.cg; + } + + public static ReturnInstruction createReturn(Type type) { + switch (type.getType()) { + case 4: + case 5: + case 8: + case 9: + case 10: + return IRETURN; + case 6: + return FRETURN; + case 7: + return DRETURN; + case 11: + return LRETURN; + case 12: + return RETURN; + case 13: + case 14: + return ARETURN; + default: + throw new RuntimeException(("Invalid type: " + type)); + } + } + + public static final ArithmeticInstruction createArithmeticInstruction(char value) { + switch (value) { + case '*': + return FMUL; + case '+': + return FADD; + case ',': + case '.': + default: + throw new RuntimeException(("Invalid operand " + value)); + case '-': + return FSUB; + case '/': + return FDIV; + } + } + + public static Instruction createThis() { + return new ALOAD(0); + } + + public InstructionList createPrintln(String text) { + InstructionList instructionList = new InstructionList(); + int value = this.cp.addFieldref("java.lang.System", "out", "Ljava/io/PrintStream;"); + int value2 = this.cp.addMethodref("java.io.PrintStream", "println", "(Ljava/lang/String;)V"); + instructionList.getInstructionHandle(new GETSTATIC(value)); + instructionList.getInstructionHandle(new PUSH(this.cp, text)); + instructionList.getInstructionHandle(new INVOKEVIRTUAL(value2)); + return instructionList; + } + + public NEW createNew(String text) { + return this.createNew(new ObjectType(text)); + } + + public static Instruction createNull(Type type) { + switch (type.getType()) { + case 4: + case 5: + case 8: + case 9: + case 10: + return ICONST_0; + case 6: + return FCONST_0; + case 7: + return DCONST_0; + case 11: + return LCONST_0; + case 12: + return NOP; + case 13: + case 14: + return ACONST_NULL; + default: + throw new RuntimeException(("Invalid type: " + type)); + } + } + + public InvokeInstruction createInvoke( + String text, String text2, Type type, Type[] types, short value) { + int value2 = 0; + String methodSignature = Type.getMethodSignature(type, types); + int value3; + for (int value4 = value3 = 0; value4 < types.length; value4 = value3) { + Type type2 = types[value3]; + int value5 = value2; + value3++; + value2 = value5 + type2.getSize(); + } + int value6; + short value7; + if (value == 185) { + value6 = this.cp.addInterfaceMethodref(text, text2, methodSignature); + value7 = value; + } else { + value6 = this.cp.addMethodref(text, text2, methodSignature); + value7 = value; + } + switch (value7) { + case 182: + return new INVOKEVIRTUAL(value6); + case 183: + return new INVOKESPECIAL(value6); + case 184: + return new INVOKESTATIC(value6); + case 185: + return new INVOKEINTERFACE(value6, value2 + 1); + default: + throw new RuntimeException(("Oops: Unknown invoke kind:" + value)); + } + } + + public InstructionFactory(ConstantPoolGen constantPoolGen) { + this(null, constantPoolGen); + } + + public static final ArithmeticInstruction createArithmeticInstruction2(char value) { + switch (value) { + case '*': + return DMUL; + case '+': + return DADD; + case ',': + case '.': + default: + throw new RuntimeException(("Invalid operand " + value)); + case '-': + return DSUB; + case '/': + return DDIV; + } + } + + public static final ArithmeticInstruction createArithmeticInstruction2(char value, String text) { + switch (value) { + case '%': + return IREM; + case '&': + return IAND; + case '*': + return IMUL; + case '+': + return IADD; + case '-': + return ISUB; + case '/': + return IDIV; + case '<': + return ISHL; + case '>': + if (text.equals(">>>")) { + return IUSHR; + } + return ISHR; + case '^': + return IXOR; + case '|': + return IOR; + default: + throw new RuntimeException(("Invalid operand " + text)); + } + } + + public Instruction createConstant(Object result) { + PUSH pUSH; + if (result instanceof Number) { + pUSH = new PUSH(this.cp, (Number) result); + } else if (result instanceof String) { + pUSH = new PUSH(this.cp, (String) result); + } else if (result instanceof Boolean) { + pUSH = new PUSH(this.cp, (Boolean) result); + } else { + if (!(result instanceof Character)) { + throw new ClassGenException(("Illegal type: " + result.getClass())); + } + pUSH = new PUSH(this.cp, (Character) result); + } + return pUSH.getInstruction(); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/InstructionHandle.java b/src/main/java/com/allatori/lib/bcel/generic/InstructionHandle.java new file mode 100644 index 0000000..9c2aedb --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/InstructionHandle.java @@ -0,0 +1,169 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.classfile.Utility; +import java.io.Serializable; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +public class InstructionHandle implements Serializable { + + public int i_position; + + public Set targeters; + + public InstructionHandle instructionHandle; + + public Map attributes; + + public static InstructionHandle ih_list = null; + + public Instruction instruction; + + public InstructionHandle instructionHandle2; + + public void setPosition(int i_position) { + this.i_position = i_position; + } + + public void accept(Visitor visitor) { + this.instruction.accept(visitor); + } + + public final InstructionHandle getInstructionHandle() { + return this.instructionHandle; + } + + public InstructionTargeter[] getTargeters() { + if (!this.hasTargeters()) { + return null; + } + InstructionTargeter[] instructionTargeters = new InstructionTargeter[this.targeters.size()]; + this.targeters.toArray(instructionTargeters); + return instructionTargeters; + } + + public void removeAllTargeters() { + if (this.targeters != null) { + this.targeters.clear(); + } + } + + public void removeAttribute(Object result) { + if (this.attributes != null) { + this.attributes.remove(result); + } + } + + public InstructionHandle(Instruction instruction) { + super(); + this.i_position = -1; + this.setInstruction(instruction); + } + + public void setInstruction(Instruction instruction2) { + if (instruction2 == null) { + throw new ClassGenException("Assigning null to handle"); + } + if (this.getClass() != BranchHandle.class && instruction2 instanceof BranchInstruction) { + throw new ClassGenException( + ("Assigning branch instruction " + instruction2 + " to plain handle")); + } + if (this.instruction != null) { + this.instruction.dispose(); + } + this.instruction = instruction2; + } + + public Collection getAttributes() { + if (this.attributes == null) { + this.attributes = new HashMap(3); + } + return this.attributes.values(); + } + + public void update() { + this.instructionHandle2 = this.instructionHandle = null; + this.instruction.dispose(); + this.instruction = null; + this.i_position = -1; + this.attributes = null; + this.removeAllTargeters(); + this.update2(); + } + + public int updatePosition(int i_position, int value2) { + this.i_position += i_position; + return 0; + } + + public Instruction swapInstruction(Instruction instruction2) { + Instruction instruction3 = this.instruction; + this.instruction = instruction2; + return instruction3; + } + + public String toString(boolean matches) { + return "" + + Utility.format(this.i_position, 4, false, ' ') + + ": " + + this.instruction.toString(matches); + } + + public final Instruction getInstruction() { + return this.instruction; + } + + public void update2() { + this.instructionHandle2 = ih_list; + ih_list = this; + } + + public void addTargeter(InstructionTargeter instructionTargeter) { + if (this.targeters == null) { + this.targeters = new HashSet(); + } + this.targeters.add(instructionTargeter); + } + + public Object getAttribute(Object result) { + return this.attributes != null ? this.attributes.get(result) : null; + } + + public void removeTargeter(InstructionTargeter instructionTargeter) { + if (this.targeters != null) { + this.targeters.remove(instructionTargeter); + } + } + + public boolean hasTargeters() { + return this.targeters != null && this.targeters.size() > 0; + } + + public static final InstructionHandle getInstructionHandle(Instruction instruction) { + if (ih_list == null) { + return new InstructionHandle(instruction); + } + InstructionHandle instructionHandle = ih_list; + ih_list = instructionHandle.instructionHandle2; + instructionHandle.setInstruction(instruction); + return instructionHandle; + } + + public void addAttribute(Object result, Object result2) { + if (this.attributes == null) { + this.attributes = new HashMap(3); + } + this.attributes.put(result, result2); + } + + public final InstructionHandle getInstructionHandle2() { + return this.instructionHandle2; + } + + public int getPosition() { + return this.i_position; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/InstructionList$1.java b/src/main/java/com/allatori/lib/bcel/generic/InstructionList$1.java new file mode 100644 index 0000000..32f2c61 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/InstructionList$1.java @@ -0,0 +1,37 @@ +package com.allatori.lib.bcel.generic; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +public class InstructionList$1 implements Iterator { + + public final InstructionList this$0; + + public InstructionHandle ih; + + @Override + public boolean hasNext() { + return this.ih != null; + } + + public InstructionList$1(InstructionList instructionList) { + super(); + this.this$0 = instructionList; + this.ih = InstructionList.access$000(this.this$0); + } + + @Override + public Object next() { + if (this.ih == null) { + throw new NoSuchElementException(); + } + InstructionHandle instructionHandle = this.ih; + this.ih = this.ih.instructionHandle2; + return instructionHandle; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/InstructionList.java b/src/main/java/com/allatori/lib/bcel/generic/InstructionList.java new file mode 100644 index 0000000..26fa0ea --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/InstructionList.java @@ -0,0 +1,938 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.Constants; +import com.allatori.lib.bcel.classfile.Constant; +import com.allatori.lib.bcel.util.ByteSequence; +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; + +public class InstructionList implements Serializable { + + public int length; + + public List observers; + + public int[] byte_positions; + + public InstructionHandle end; + + public InstructionHandle start = null; + + public InstructionHandle findHandle(int value) { + return findHandle(this.getInstructionHandles(), this.byte_positions, this.length, value); + } + + public void redirectLocalVariables( + LocalVariableGen[] localVariableGens, + InstructionHandle instructionHandle, + InstructionHandle instructionHandle2) { + int value; + for (int value2 = value = 0; value2 < localVariableGens.length; value2 = ++value) { + InstructionHandle instructionHandle3 = localVariableGens[value].getInstructionHandle(); + InstructionHandle instructionHandle22 = localVariableGens[value].getInstructionHandle2(); + if (instructionHandle3 == instructionHandle) { + localVariableGens[value].processInstructionHandle2(instructionHandle2); + } + if (instructionHandle22 == instructionHandle) { + localVariableGens[value].processInstructionHandle(instructionHandle2); + } + } + } + + public void processInstructionHandle( + InstructionHandle instructionHandle3, InstructionHandle instructionHandle4) + throws TargetLostException { + this.processInstructionHandle4( + instructionHandle3.instructionHandle, instructionHandle4.instructionHandle2); + } + + public InstructionHandle createInstructionHandle( + Instruction instruction, Instruction instruction2) { + return this.createInstructionHandle(instruction, new InstructionList(instruction2)); + } + + public Instruction[] getInstructions() { + ByteSequence byteSequence = new ByteSequence(this.getByteCode()); + ArrayList values = new ArrayList(); + try { + while (byteSequence.available() > 0) { + values.add(Instruction.readInstruction(byteSequence)); + } + } catch (IOException oException) { + throw new ClassGenException(oException.toString()); + } + return (Instruction[]) values.toArray(new Instruction[values.size()]); + } + + public InstructionHandle getInstructionHandle(Instruction instruction) { + InstructionHandle instructionHandle = InstructionHandle.getInstructionHandle(instruction); + this.processInstructionHandle(instructionHandle); + return instructionHandle; + } + + public InstructionHandle createInstructionHandle( + InstructionHandle instructionHandle, Instruction instruction) { + return this.createInstructionHandle(instructionHandle, new InstructionList(instruction)); + } + + public InstructionHandle getInstructionHandle2(Instruction instruction2) { + InstructionHandle instructionHandle; + for (InstructionHandle instructionHandle3 = instructionHandle = this.start; + instructionHandle3 != null; + instructionHandle3 = instructionHandle = instructionHandle.instructionHandle2) { + if (instructionHandle.instruction == instruction2) { + return instructionHandle; + } + } + return null; + } + + public int getLength() { + return this.length; + } + + public void addObserver(InstructionListObserver instructionListObserver) { + if (this.observers == null) { + this.observers = new ArrayList(); + } + this.observers.add(instructionListObserver); + } + + public InstructionHandle createInstructionHandle2( + InstructionHandle instructionHandle, Instruction instruction) { + return this.createInstructionHandle2(instructionHandle, new InstructionList(instruction)); + } + + public BranchHandle getBranchHandle(BranchInstruction branchInstruction) { + BranchHandle branchHandle = BranchHandle.getBranchHandle(branchInstruction); + this.processInstructionHandle(branchHandle); + return branchHandle; + } + + public InstructionHandle createInstructionHandle( + InstructionHandle instructionHandle3, InstructionList instructionList) { + if (instructionList == null) { + throw new ClassGenException("Inserting null InstructionList"); + } + if (instructionList.isEmpty()) { + return instructionHandle3; + } + InstructionHandle instructionHandle4 = instructionHandle3.instructionHandle; + InstructionHandle instructionHandle5 = instructionList.start; + instructionHandle3.instructionHandle = instructionList.end; + instructionList.end.instructionHandle2 = instructionHandle3; + InstructionList instructionList2; + if ((instructionList.start.instructionHandle = instructionHandle4) != null) { + instructionList2 = this; + instructionHandle4.instructionHandle2 = instructionList.start; + } else { + instructionList2 = this; + this.start = instructionList.start; + } + instructionList2.length = instructionList2.length + instructionList.length; + instructionList.update4(); + return instructionHandle5; + } + + public void update() { + this.setPositions(false); + } + + public void removeObserver(InstructionListObserver instructionListObserver) { + if (this.observers != null) { + this.observers.remove(instructionListObserver); + } + } + + public BranchHandle getBranchHandle2(BranchInstruction branchInstruction) { + BranchHandle branchHandle = BranchHandle.getBranchHandle(branchInstruction); + this.processInstructionHandle3(branchHandle); + return branchHandle; + } + + public void update2() { + Iterator iterator2; + if (this.observers != null) { + for (Iterator iterator3 = iterator2 = this.observers.iterator(); + iterator3.hasNext(); + iterator3 = iterator2) { + ((InstructionListObserver) iterator2.next()).notify(this); + } + } + } + + public Iterator iterator() { + return new InstructionList$1(this); + } + + public BranchHandle createBranchHandle( + InstructionHandle instructionHandle, BranchInstruction branchInstruction) { + BranchHandle branchHandle = BranchHandle.getBranchHandle(branchInstruction); + InstructionList instructionList = new InstructionList(); + instructionList.processInstructionHandle(branchHandle); + this.createInstructionHandle2(instructionHandle, instructionList); + return branchHandle; + } + + public void delete(Instruction instruction) throws TargetLostException { + InstructionHandle instructionHandle; + if ((instructionHandle = this.getInstructionHandle2(instruction)) == null) { + throw new ClassGenException( + ("Instruction " + instruction + " is not contained in this list.")); + } + this.processInstructionHandle2(instructionHandle); + } + + public void delete(Instruction instruction, Instruction instruction2) throws TargetLostException { + InstructionHandle instructionHandle; + if ((instructionHandle = this.getInstructionHandle2(instruction)) == null) { + throw new ClassGenException( + ("Instruction " + instruction + " is not contained in this list.")); + } + InstructionHandle instructionHandle2; + if ((instructionHandle2 = this.getInstructionHandle3(instruction2)) == null) { + throw new ClassGenException( + ("Instruction " + instruction2 + " is not contained in this list.")); + } + this.processInstructionHandle(instructionHandle, instructionHandle2); + } + + public InstructionHandle createInstructionHandle2( + InstructionHandle instructionHandle3, InstructionList instructionList) { + if (instructionList == null) { + throw new ClassGenException("Appending null InstructionList"); + } + if (instructionList.isEmpty()) { + return instructionHandle3; + } + InstructionHandle instructionHandle4 = instructionHandle3.instructionHandle2; + InstructionHandle instructionHandle5 = instructionList.start; + instructionHandle3.instructionHandle2 = instructionList.start; + instructionList.start.instructionHandle = instructionHandle3; + InstructionList instructionList2; + if ((instructionList.end.instructionHandle2 = instructionHandle4) != null) { + instructionList2 = this; + instructionHandle4.instructionHandle = instructionList.end; + } else { + instructionList2 = this; + this.end = instructionList.end; + } + instructionList2.length = instructionList2.length + instructionList.length; + instructionList.update4(); + return instructionHandle5; + } + + public InstructionHandle getInstructionHandle( + Instruction instruction, CompoundInstruction compoundInstruction) { + return this.createInstructionHandle(instruction, compoundInstruction.getInstructionList()); + } + + public boolean contains(InstructionHandle instructionHandle) { + if (instructionHandle == null) { + return false; + } + InstructionHandle instructionHandle3; + for (InstructionHandle instructionHandle4 = instructionHandle3 = this.start; + instructionHandle4 != null; + instructionHandle4 = instructionHandle3 = instructionHandle3.instructionHandle2) { + if (instructionHandle3 == instructionHandle) { + return true; + } + } + return false; + } + + public InstructionList(byte[] values) { + this.end = null; + this.length = 0; + ByteSequence byteSequence = new ByteSequence(values); + InstructionHandle[] instructionHandles = new InstructionHandle[values.length]; + int[] values2 = new int[values.length]; + int value = 0; + try { + while (byteSequence.available() > 0) { + int index = byteSequence.getIndex(); + values2[value] = index; + InstructionHandle instructionHandle; + Instruction instruction2; + ((instruction2 = Instruction.readInstruction(byteSequence)) instanceof BranchInstruction + ? (instructionHandle = this.getBranchHandle((BranchInstruction) instruction2)) + : (instructionHandle = this.getInstructionHandle(instruction2))) + .setPosition(index); + InstructionHandle instructionHandle2 = instructionHandle; + int value2 = value; + value++; + instructionHandles[value2] = instructionHandle2; + } + } catch (IOException oException) { + throw new ClassGenException(oException.toString()); + } + this.byte_positions = new int[value]; + int value3 = 0; + System.arraycopy(values2, 0, this.byte_positions, 0, value); + for (int index2 = 0; value3 < value; value3 = ++index2) { + if (instructionHandles[index2] instanceof BranchHandle) { + BranchInstruction branchInstruction = + (BranchInstruction) instructionHandles[index2].instruction; + int value4 = branchInstruction.count + branchInstruction.getIndex(); + InstructionHandle instructionHandle3; + if ((instructionHandle3 = findHandle(instructionHandles, values2, value, value4)) == null) { + throw new ClassGenException(("Couldn't find target for branch: " + branchInstruction)); + } + branchInstruction.setTarget(instructionHandle3); + if (branchInstruction instanceof Select) { + Select select; + int[] indices = (select = (Select) branchInstruction).getIndices(); + int value5; + for (int value6 = value5 = 0; value6 < indices.length; value6 = value5) { + int value7 = branchInstruction.count + indices[value5]; + InstructionHandle instructionHandle4; + if ((instructionHandle4 = findHandle(instructionHandles, values2, value, value7)) + == null) { + throw new ClassGenException( + ("Couldn't find target for switch: " + branchInstruction)); + } + int value8 = value5; + Select select2 = select; + value5++; + select2.setTarget(value8, instructionHandle4); + } + } + } + } + } + + public InstructionHandle createInstructionHandle( + Instruction instruction, InstructionList instructionList) { + InstructionHandle instructionHandle; + if ((instructionHandle = this.getInstructionHandle3(instruction)) == null) { + throw new ClassGenException( + ("Instruction " + instruction + " is not contained in this list.")); + } else { + return this.createInstructionHandle2(instructionHandle, instructionList); + } + } + + public InstructionHandle getInstructionHandle(CompoundInstruction compoundInstruction) { + return this.append(compoundInstruction.getInstructionList()); + } + + public InstructionHandle getInstructionHandle3(Instruction instruction2) { + InstructionHandle instructionHandle2; + for (InstructionHandle instructionHandle3 = instructionHandle2 = this.end; + instructionHandle3 != null; + instructionHandle3 = instructionHandle2 = instructionHandle2.instructionHandle) { + if (instructionHandle2.instruction == instruction2) { + return instructionHandle2; + } + } + return null; + } + + public void move( + InstructionHandle instructionHandle3, + InstructionHandle instructionHandle4, + InstructionHandle instructionHandle5) { + if (instructionHandle3 != null && instructionHandle4 != null) { + if (instructionHandle5 != instructionHandle3 && instructionHandle5 != instructionHandle4) { + InstructionHandle instructionHandle6; + for (InstructionHandle instructionHandle7 = instructionHandle6 = instructionHandle3; + instructionHandle7 != instructionHandle4.instructionHandle2; + instructionHandle7 = instructionHandle6 = instructionHandle6.instructionHandle2) { + if (instructionHandle6 == null) { + throw new ClassGenException( + ("Invalid range: From " + instructionHandle3 + " to " + instructionHandle4)); + } + if (instructionHandle6 == instructionHandle5) { + throw new ClassGenException( + ("Invalid range: From " + + instructionHandle3 + + " to " + + instructionHandle4 + + " contains target " + + instructionHandle5)); + } + } + InstructionHandle instructionHandle8 = instructionHandle3.instructionHandle; + InstructionHandle instructionHandle9 = instructionHandle4.instructionHandle2; + InstructionHandle instructionHandle10; + if (instructionHandle8 != null) { + instructionHandle10 = instructionHandle8.instructionHandle2 = instructionHandle9; + } else { + this.start = instructionHandle9; + instructionHandle10 = instructionHandle9; + } + if (instructionHandle10 != null) { + instructionHandle10 = instructionHandle3; + instructionHandle9.instructionHandle = instructionHandle8; + } else { + this.end = instructionHandle8; + instructionHandle10 = instructionHandle3; + } + instructionHandle10.instructionHandle = instructionHandle4.instructionHandle2 = null; + if (instructionHandle5 == null) { + if (this.start != null) { + this.start.instructionHandle = instructionHandle4; + } + instructionHandle4.instructionHandle2 = this.start; + this.start = instructionHandle3; + } else { + InstructionHandle instructionHandle11 = instructionHandle5.instructionHandle2; + instructionHandle5.instructionHandle2 = instructionHandle3; + instructionHandle3.instructionHandle = instructionHandle5; + instructionHandle4.instructionHandle2 = instructionHandle11; + if (instructionHandle11 != null) { + instructionHandle11.instructionHandle = instructionHandle4; + } else { + this.end = instructionHandle4; + } + } + } else { + throw new ClassGenException( + ("Invalid range: From " + + instructionHandle3 + + " to " + + instructionHandle4 + + " contains target " + + instructionHandle5)); + } + } else { + throw new ClassGenException( + ("Invalid null handle: From " + instructionHandle3 + " to " + instructionHandle4)); + } + } + + public void replaceConstantPool( + ConstantPoolGen constantPoolGen, ConstantPoolGen constantPoolGen2) { + InstructionHandle instructionHandle; + for (InstructionHandle instructionHandle3 = instructionHandle = this.start; + instructionHandle3 != null; + instructionHandle3 = instructionHandle = instructionHandle.instructionHandle2) { + Instruction instruction2 = instructionHandle.instruction; + if (instructionHandle.instruction instanceof CPInstruction) { + CPInstruction cPInstruction = (CPInstruction) instruction2; + Constant constant = constantPoolGen.getConstant(cPInstruction.getIndex()); + cPInstruction.setIndex(constantPoolGen2.addConstant(constant, constantPoolGen)); + } + } + } + + public InstructionHandle append(InstructionList instructionList) { + if (instructionList == null) { + throw new ClassGenException("Appending null InstructionList"); + } else if (instructionList.isEmpty()) { + return null; + } else if (this.isEmpty()) { + this.start = instructionList.start; + this.end = instructionList.end; + this.length = instructionList.length; + instructionList.update4(); + return this.start; + } else { + return this.createInstructionHandle2(this.end, instructionList); + } + } + + public static InstructionHandle access$000(InstructionList instructionList) { + return instructionList.start; + } + + public InstructionHandle getInstructionHandle( + InstructionHandle instructionHandle, CompoundInstruction compoundInstruction) { + return this.createInstructionHandle( + instructionHandle, compoundInstruction.getInstructionList()); + } + + public InstructionHandle getStart() { + return this.start; + } + + public int getLength2() { + return this.length; + } + + public void processInstructionHandle2( + InstructionHandle instructionHandle, InstructionHandle instructionHandle3) { + InstructionHandle instructionHandle4; + for (InstructionHandle instructionHandle5 = instructionHandle4 = this.start; + instructionHandle5 != null; + instructionHandle5 = instructionHandle4 = instructionHandle4.instructionHandle2) { + Instruction instruction; + if ((instruction = instructionHandle4.getInstruction()) instanceof BranchInstruction) { + BranchInstruction branchInstruction; + if ((branchInstruction = (BranchInstruction) instruction).getTarget() + == instructionHandle) { + branchInstruction.setTarget(instructionHandle3); + } + if (branchInstruction instanceof Select) { + InstructionHandle[] targets = ((Select) branchInstruction).getTargets(); + int value; + for (int value2 = value = 0; value2 < targets.length; value2 = ++value) { + if (targets[value] == instructionHandle) { + ((Select) branchInstruction).setTarget(value, instructionHandle3); + } + } + } + } + } + } + + public InstructionHandle getInstructionHandle2( + Instruction instruction, CompoundInstruction compoundInstruction) { + return this.createInstructionHandle2(instruction, compoundInstruction.getInstructionList()); + } + + public void update3() { + InstructionHandle instructionHandle2; + for (InstructionHandle instructionHandle3 = instructionHandle2 = this.end; + instructionHandle3 != null; + instructionHandle3 = instructionHandle2 = instructionHandle2.instructionHandle) { + instructionHandle2.update(); + } + this.update4(); + } + + public void processInstructionHandle3( + InstructionHandle instructionHandle, InstructionHandle instructionHandle2) { + this.move(instructionHandle, instructionHandle, instructionHandle2); + } + + public void processInstructionHandle(InstructionHandle instructionHandle3) { + InstructionList instructionList; + if (this.isEmpty()) { + this.start = this.end = instructionHandle3; + instructionHandle3.instructionHandle2 = instructionHandle3.instructionHandle = null; + instructionList = this; + } else { + instructionList = this; + this.end.instructionHandle2 = instructionHandle3; + instructionHandle3.instructionHandle = this.end; + instructionHandle3.instructionHandle2 = null; + this.end = instructionHandle3; + } + instructionList.length++; + } + + public InstructionHandle createInstructionHandle2( + Instruction instruction, InstructionList instructionList) { + InstructionHandle instructionHandle; + if ((instructionHandle = this.getInstructionHandle2(instruction)) == null) { + throw new ClassGenException( + ("Instruction " + instruction + " is not contained in this list.")); + } else { + return this.createInstructionHandle(instructionHandle, instructionList); + } + } + + public byte[] getByteCode() { + this.update(); + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + DataOutputStream dataOutputStream = new DataOutputStream(byteArrayOutputStream); + try { + for (InstructionHandle instructionHandle = this.start; + instructionHandle != null; + instructionHandle = instructionHandle.instructionHandle2) { + instructionHandle.instruction.dump(dataOutputStream); + } + } catch (IOException oException) { + System.err.println(oException); + return null; + } + return byteArrayOutputStream.toByteArray(); + } + + public String toString(boolean matches) { + StringBuffer stringBuffer = new StringBuffer(); + InstructionHandle instructionHandle; + for (InstructionHandle instructionHandle3 = instructionHandle = this.start; + instructionHandle3 != null; + instructionHandle3 = instructionHandle) { + stringBuffer.append(instructionHandle.toString(matches)).append("\n"); + instructionHandle = instructionHandle.instructionHandle2; + } + return stringBuffer.toString(); + } + + public InstructionList(CompoundInstruction compoundInstruction) { + super(); + this.start = null; + this.end = null; + this.length = 0; + this.append(compoundInstruction.getInstructionList()); + } + + public InstructionHandle getEnd() { + return this.end; + } + + public InstructionHandle getInstructionHandle2( + InstructionHandle instructionHandle, CompoundInstruction compoundInstruction) { + return this.createInstructionHandle2( + instructionHandle, compoundInstruction.getInstructionList()); + } + + public InstructionList(BranchInstruction branchInstruction) { + super(); + this.start = null; + this.end = null; + this.length = 0; + this.getBranchHandle(branchInstruction); + } + + public void processInstructionHandle4( + InstructionHandle instructionHandle3, InstructionHandle instructionHandle4) + throws TargetLostException { + InstructionHandle instructionHandle5; + InstructionHandle instructionHandle6; + InstructionHandle instructionHandle7; + if (instructionHandle3 == null && instructionHandle4 == null) { + instructionHandle6 = this.start; + instructionHandle5 = this.start; + this.start = this.end = null; + instructionHandle7 = instructionHandle5; + } else { + if (instructionHandle3 == null) { + instructionHandle5 = this.start; + this.start = instructionHandle4; + instructionHandle7 = instructionHandle4; + } else { + instructionHandle5 = instructionHandle3.instructionHandle2; + instructionHandle3.instructionHandle2 = instructionHandle4; + instructionHandle7 = instructionHandle4; + } + if (instructionHandle7 == null) { + instructionHandle6 = this.end; + this.end = instructionHandle3; + instructionHandle7 = instructionHandle5; + } else { + instructionHandle6 = instructionHandle4.instructionHandle; + instructionHandle4.instructionHandle = instructionHandle3; + instructionHandle7 = instructionHandle5; + } + } + instructionHandle7.instructionHandle = null; + instructionHandle6.instructionHandle2 = null; + ArrayList values = new ArrayList(); + InstructionHandle instructionHandle8; + for (InstructionHandle instructionHandle9 = instructionHandle8 = instructionHandle5; + instructionHandle9 != null; + instructionHandle9 = instructionHandle8 = instructionHandle8.instructionHandle2) { + instructionHandle8.getInstruction().dispose(); + } + StringBuffer stringBuffer = new StringBuffer("{ "); + InstructionHandle instructionHandle10; + for (instructionHandle7 = instructionHandle10 = instructionHandle5; + instructionHandle7 != null; + instructionHandle7 = instructionHandle10) { + InstructionHandle instructionHandle11 = instructionHandle10.instructionHandle2; + this.length--; + if (instructionHandle10.hasTargeters()) { + values.add(instructionHandle10); + stringBuffer.append(instructionHandle10.toString(true) + " "); + instructionHandle10.instructionHandle2 = instructionHandle10.instructionHandle = null; + instructionHandle7 = instructionHandle11; + } else { + instructionHandle10.update(); + instructionHandle7 = instructionHandle11; + } + instructionHandle10 = instructionHandle7; + } + stringBuffer.append("}"); + if (!values.isEmpty()) { + InstructionHandle[] instructionHandles = new InstructionHandle[values.size()]; + values.toArray(instructionHandles); + throw new TargetLostException(instructionHandles, stringBuffer.toString()); + } + } + + public BranchHandle createBranchHandle2( + InstructionHandle instructionHandle, BranchInstruction branchInstruction) { + BranchHandle branchHandle = BranchHandle.getBranchHandle(branchInstruction); + InstructionList instructionList = new InstructionList(); + instructionList.processInstructionHandle(branchHandle); + this.createInstructionHandle(instructionHandle, instructionList); + return branchHandle; + } + + public void redirectExceptionHandlers( + CodeExceptionGen[] codeExceptionGens, + InstructionHandle instructionHandle, + InstructionHandle instructionHandle2) { + int value; + for (int value2 = value = 0; value2 < codeExceptionGens.length; value2 = ++value) { + if (codeExceptionGens[value].getInstructionHandle2() == instructionHandle) { + codeExceptionGens[value].processInstructionHandle2(instructionHandle2); + } + if (codeExceptionGens[value].getInstructionHandle() == instructionHandle) { + codeExceptionGens[value].processInstructionHandle(instructionHandle2); + } + if (codeExceptionGens[value].getInstructionHandle3() == instructionHandle) { + codeExceptionGens[value].processInstructionHandle3(instructionHandle2); + } + } + } + + public void processInstructionHandle2(InstructionHandle instructionHandle3) + throws TargetLostException { + this.processInstructionHandle4( + instructionHandle3.instructionHandle, instructionHandle3.instructionHandle2); + } + + public InstructionList(Instruction instruction) { + super(); + this.start = null; + this.end = null; + this.length = 0; + this.getInstructionHandle(instruction); + } + + public InstructionHandle getInstructionHandle4(Instruction instruction) { + InstructionHandle instructionHandle = InstructionHandle.getInstructionHandle(instruction); + this.processInstructionHandle3(instructionHandle); + return instructionHandle; + } + + public int[] getInstructionPositions() { + return this.byte_positions; + } + + public boolean isEmpty() { + return this.start == null; + } + + public InstructionList() { + this.end = null; + this.length = 0; + } + + public InstructionHandle insert(InstructionList instructionList) { + if (this.isEmpty()) { + this.append(instructionList); + return this.start; + } else { + return this.createInstructionHandle(this.start, instructionList); + } + } + + public InstructionHandle getInstructionHandle2(CompoundInstruction compoundInstruction) { + return this.insert(compoundInstruction.getInstructionList()); + } + + public void processInstructionHandle3(InstructionHandle instructionHandle3) { + InstructionList instructionList; + if (this.isEmpty()) { + this.start = this.end = instructionHandle3; + instructionHandle3.instructionHandle2 = instructionHandle3.instructionHandle = null; + instructionList = this; + } else { + instructionList = this; + this.start.instructionHandle = instructionHandle3; + instructionHandle3.instructionHandle2 = this.start; + instructionHandle3.instructionHandle = null; + this.start = instructionHandle3; + } + instructionList.length++; + } + + public InstructionList copy() { + HashMap entries = new HashMap(); + InstructionList instructionList = new InstructionList(); + InstructionHandle instructionHandle; + InstructionHandle instructionHandle3 = instructionHandle = this.start; + while (instructionHandle3 != null) { + Instruction instruction2; + if ((instruction2 = instructionHandle.instruction.copy()) instanceof BranchInstruction) { + entries.put( + instructionHandle, instructionList.getBranchHandle((BranchInstruction) instruction2)); + instructionHandle3 = instructionHandle; + } else { + entries.put(instructionHandle, instructionList.getInstructionHandle(instruction2)); + instructionHandle3 = instructionHandle; + } + instructionHandle3 = instructionHandle = instructionHandle3.instructionHandle2; + } + InstructionHandle instructionHandle4 = this.start; + InstructionHandle instructionHandle5 = instructionList.start; + for (InstructionHandle instructionHandle6 = instructionHandle4; + instructionHandle6 != null; + instructionHandle6 = instructionHandle4) { + Instruction instruction3 = instructionHandle4.instruction; + Instruction instruction4 = instructionHandle5.instruction; + if (instruction3 instanceof BranchInstruction) { + BranchInstruction branchInstruction = (BranchInstruction) instruction3; + BranchInstruction branchInstruction2 = (BranchInstruction) instruction4; + InstructionHandle target = branchInstruction.getTarget(); + branchInstruction2.setTarget((InstructionHandle) entries.get(target)); + if (branchInstruction instanceof Select) { + InstructionHandle[] targets = ((Select) branchInstruction).getTargets(); + InstructionHandle[] targets2 = ((Select) branchInstruction2).getTargets(); + int value; + for (int value2 = value = 0; value2 < targets.length; value2 = value) { + InstructionHandle instructionHandle7 = (InstructionHandle) entries.get(targets[value]); + int value3 = value; + value++; + targets2[value3] = instructionHandle7; + } + } + } + instructionHandle4 = instructionHandle4.instructionHandle2; + instructionHandle5 = instructionHandle5.instructionHandle2; + } + return instructionList; + } + + public void setPositions(boolean matches) { + int value = 0; + int value2 = 0; + int value3 = 0; + int value4 = 0; + int[] values = new int[this.length]; + InstructionHandle instructionHandle; + if (matches) { + for (InstructionHandle instructionHandle3 = instructionHandle = this.start; + instructionHandle3 != null; + instructionHandle3 = instructionHandle = instructionHandle.instructionHandle2) { + Instruction instruction2 = instructionHandle.instruction; + if (instructionHandle.instruction instanceof BranchInstruction) { + Instruction instruction3 = ((BranchInstruction) instruction2).getTarget().instruction; + if (!this.contains(instruction3)) { + throw new ClassGenException( + ("Branch target of " + + Constants.TEXTS8[instruction2.opcode] + + ":" + + instruction3 + + " not in instruction list")); + } + if (instruction2 instanceof Select) { + InstructionHandle[] targets = ((Select) instruction2).getTargets(); + int value5; + for (int value6 = value5 = 0; value6 < targets.length; value6 = ++value5) { + instruction3 = targets[value5].instruction; + if (!this.contains(instruction3)) { + throw new ClassGenException( + ("Branch target of " + + Constants.TEXTS8[instruction2.opcode] + + ":" + + instruction3 + + " not in instruction list")); + } + } + } + if (!(instructionHandle instanceof BranchHandle)) { + throw new ClassGenException( + ("Branch instruction " + + Constants.TEXTS8[instruction2.opcode] + + ":" + + instruction3 + + " not contained in BranchHandle.")); + } + } + } + } + InstructionHandle instructionHandle4; + for (InstructionHandle instructionHandle5 = instructionHandle4 = this.start; + instructionHandle5 != null; + instructionHandle5 = instructionHandle4 = instructionHandle4.instructionHandle2) { + Instruction instruction4 = instructionHandle4.instruction; + instructionHandle4.setPosition(value3); + int value7 = value3; + int value8 = value4; + value4++; + values[value8] = value7; + int value9; + switch (instruction4.getOpcode()) { + case 167: + case 168: + value += 2; + value9 = value3; + break; + case 170: + case 171: + value += 3; + case 169: + default: + value9 = value3; + } + value3 = value9 + instruction4.getLength(); + } + InstructionHandle instructionHandle6; + for (InstructionHandle instructionHandle7 = instructionHandle6 = this.start; + instructionHandle7 != null; + instructionHandle7 = instructionHandle6 = instructionHandle6.instructionHandle2) { + value2 += instructionHandle6.updatePosition(value2, value); + } + int value10 = 0; + int value11 = 0; + InstructionHandle instructionHandle8; + InstructionHandle instructionHandle9 = instructionHandle8 = this.start; + while (instructionHandle9 != null) { + Instruction instruction5 = instructionHandle8.instruction; + instructionHandle8.setPosition(value11); + int value12 = value11; + int value13 = value10; + InstructionHandle instructionHandle10 = instructionHandle8; + value10++; + values[value13] = value12; + value11 += instruction5.getLength(); + instructionHandle9 = instructionHandle8 = instructionHandle10.instructionHandle2; + } + this.byte_positions = new int[value10]; + System.arraycopy(values, 0, this.byte_positions, 0, value10); + } + + public void update4() { + this.start = this.end = null; + this.length = 0; + } + + public static InstructionHandle findHandle( + InstructionHandle[] instructionHandles, int[] values, int value, int value2) { + int value3 = 0; + int value4 = value - 1; + int value5; + do { + int value6 = (value3 + value4) / 2; + int value7; + if ((value7 = values[value6]) == value2) { + return instructionHandles[value6]; + } + if (value2 < value7) { + value4 = value6 - 1; + value5 = value3; + } else { + value5 = value3 = value6 + 1; + } + } while (value5 <= value4); + return null; + } + + public InstructionHandle[] getInstructionHandles() { + InstructionHandle[] instructionHandles = new InstructionHandle[this.length]; + InstructionHandle instructionHandle = this.start; + int value; + for (int value2 = value = 0; value2 < this.length; value2 = value) { + InstructionHandle instructionHandle3; + InstructionHandle instructionHandle4 = instructionHandle3 = instructionHandle; + int value3 = value; + value++; + instructionHandles[value3] = instructionHandle3; + instructionHandle = instructionHandle4.instructionHandle2; + } + return instructionHandles; + } + + public boolean contains(Instruction instruction) { + return this.getInstructionHandle2(instruction) != null; + } + + public InstructionHandle createInstructionHandle2( + Instruction instruction, Instruction instruction2) { + return this.createInstructionHandle2(instruction, new InstructionList(instruction2)); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/InstructionListObserver.java b/src/main/java/com/allatori/lib/bcel/generic/InstructionListObserver.java new file mode 100644 index 0000000..0c99d7e --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/InstructionListObserver.java @@ -0,0 +1,6 @@ +package com.allatori.lib.bcel.generic; + +public interface InstructionListObserver { + + void notify(InstructionList instructionList); +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/InstructionTargeter.java b/src/main/java/com/allatori/lib/bcel/generic/InstructionTargeter.java new file mode 100644 index 0000000..d314250 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/InstructionTargeter.java @@ -0,0 +1,9 @@ +package com.allatori.lib.bcel.generic; + +public interface InstructionTargeter { + + void updateTarget(InstructionHandle instructionHandle, InstructionHandle instructionHandle2) + throws ClassGenException; + + boolean containsTarget(InstructionHandle instructionHandle); +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/InvokeInstruction.java b/src/main/java/com/allatori/lib/bcel/generic/InvokeInstruction.java new file mode 100644 index 0000000..70625cf --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/InvokeInstruction.java @@ -0,0 +1,72 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.Constants; +import com.allatori.lib.bcel.classfile.Constant; +import com.allatori.lib.bcel.classfile.ConstantPool; +import java.util.StringTokenizer; + +public abstract class InvokeInstruction extends FieldOrMethod + implements ExceptionThrower, TypedInstruction, StackConsumer, StackProducer { + + public Type getType2(ConstantPoolGen constantPoolGen) { + return Type.getReturnType(this.getText3(constantPoolGen)); + } + + @Override + public Type getType(ConstantPoolGen constantPoolGen) { + return this.getType2(constantPoolGen); + } + + @Override + public String toString(ConstantPool constantPool) { + Constant constant = constantPool.getConstant(this.index); + StringTokenizer stringTokenizer = new StringTokenizer(constantPool.constantToString(constant)); + return "" + + Constants.TEXTS8[this.opcode] + + " " + + stringTokenizer.nextToken().replace('.', '/') + + stringTokenizer.nextToken(); + } + + public InvokeInstruction() {} + + public String getText4(ConstantPoolGen constantPoolGen) { + return this.getText(constantPoolGen); + } + + public Type[] getArgumentTypes(ConstantPoolGen constantPoolGen) { + return Type.getArgumentTypes(this.getText3(constantPoolGen)); + } + + public InvokeInstruction(short value, int value2) { + super(value, value2); + } + + @Override + public int consumeStack(ConstantPoolGen constantPoolGen) { + Type[] argumentTypes = Type.getArgumentTypes(this.getText3(constantPoolGen)); + int value; + Type[] types; + if (this.opcode == 184) { + value = 0; + types = argumentTypes; + } else { + value = 1; + types = argumentTypes; + } + int value2 = types.length; + int value3; + for (int value4 = value3 = 0; value4 < value2; value4 = value3) { + Type type = argumentTypes[value3]; + int value5 = value; + value3++; + value = value5 + type.getSize(); + } + return value; + } + + @Override + public int produceStack(ConstantPoolGen constantPoolGen) { + return this.getType2(constantPoolGen).getSize(); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/JSR.java b/src/main/java/com/allatori/lib/bcel/generic/JSR.java new file mode 100644 index 0000000..033ad93 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/JSR.java @@ -0,0 +1,47 @@ +package com.allatori.lib.bcel.generic; + +import java.io.DataOutputStream; +import java.io.IOException; + +public class JSR extends JsrInstruction implements VariableLengthInstruction { + + @Override + public void dump(DataOutputStream dataOutputStream) throws IOException { + this.index = this.getTargetOffset(); + if (this.opcode == 168) { + super.dump(dataOutputStream); + } else { + this.index = this.getTargetOffset(); + dataOutputStream.writeByte(this.opcode); + dataOutputStream.writeInt(this.index); + } + } + + @Override + public void accept(Visitor visitor) { + visitor.visitStackProducer(this); + visitor.visitVariableLengthInstruction(this); + visitor.visitBranchInstruction(this); + visitor.visitJsrInstruction(this); + visitor.visitJSR(this); + } + + public JSR(InstructionHandle instructionHandle) { + super((short) 168, instructionHandle); + } + + public JSR() {} + + @Override + public int updatePosition(int count, int value2) { + int targetOffset = this.getTargetOffset(); + this.count += count; + if (Math.abs(targetOffset) >= 32767 - value2) { + this.opcode = 201; + this.length = 5; + return 2; + } else { + return 0; + } + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/JSR_W.java b/src/main/java/com/allatori/lib/bcel/generic/JSR_W.java new file mode 100644 index 0000000..29b5b58 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/JSR_W.java @@ -0,0 +1,36 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.util.ByteSequence; +import java.io.DataOutputStream; +import java.io.IOException; + +public class JSR_W extends JsrInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitStackProducer(this); + visitor.visitBranchInstruction(this); + visitor.visitJsrInstruction(this); + visitor.visitJSR_W(this); + } + + public JSR_W() {} + + public JSR_W(InstructionHandle instructionHandle) { + super((short) 201, instructionHandle); + this.length = 5; + } + + @Override + public void dump(DataOutputStream dataOutputStream) throws IOException { + this.index = this.getTargetOffset(); + dataOutputStream.writeByte(this.opcode); + dataOutputStream.writeInt(this.index); + } + + @Override + public void initFromFile(ByteSequence byteSequence, boolean matches) throws IOException { + this.index = byteSequence.readInt(); + this.length = 5; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/JsrInstruction.java b/src/main/java/com/allatori/lib/bcel/generic/JsrInstruction.java new file mode 100644 index 0000000..9fd5129 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/JsrInstruction.java @@ -0,0 +1,36 @@ +package com.allatori.lib.bcel.generic; + +public abstract class JsrInstruction extends BranchInstruction + implements UnconditionalBranch, TypedInstruction, StackProducer { + + public JsrInstruction() {} + + @Override + public Type getType(ConstantPoolGen constantPoolGen) { + return new ReturnaddressType(this.physicalSuccessor()); + } + + public InstructionHandle physicalSuccessor() { + InstructionHandle instructionHandle; + InstructionHandle instructionHandle2 = instructionHandle = this.target; + while (instructionHandle2.getInstructionHandle() != null) { + instructionHandle2 = instructionHandle = instructionHandle.getInstructionHandle(); + } + instructionHandle2 = instructionHandle; + while (instructionHandle2.getInstruction() != this) { + instructionHandle2 = instructionHandle = instructionHandle.getInstructionHandle2(); + } + InstructionHandle instructionHandle3 = instructionHandle; + while (instructionHandle != null) { + if ((instructionHandle = instructionHandle.getInstructionHandle2()) != null + && instructionHandle.getInstruction() == this) { + throw new RuntimeException("physicalSuccessor() called on a shared JsrInstruction."); + } + } + return instructionHandle3.getInstructionHandle2(); + } + + public JsrInstruction(short value, InstructionHandle instructionHandle) { + super(value, instructionHandle); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/L2D.java b/src/main/java/com/allatori/lib/bcel/generic/L2D.java new file mode 100644 index 0000000..0657cc3 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/L2D.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class L2D extends ConversionInstruction { + + public L2D() { + super((short) 138); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitConversionInstruction(this); + visitor.visitL2D(this); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/L2F.java b/src/main/java/com/allatori/lib/bcel/generic/L2F.java new file mode 100644 index 0000000..b56ec27 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/L2F.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class L2F extends ConversionInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitConversionInstruction(this); + visitor.visitL2F(this); + } + + public L2F() { + super((short) 137); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/L2I.java b/src/main/java/com/allatori/lib/bcel/generic/L2I.java new file mode 100644 index 0000000..e504550 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/L2I.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class L2I extends ConversionInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitConversionInstruction(this); + visitor.visitL2I(this); + } + + public L2I() { + super((short) 136); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/LADD.java b/src/main/java/com/allatori/lib/bcel/generic/LADD.java new file mode 100644 index 0000000..c2c087e --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/LADD.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class LADD extends ArithmeticInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitArithmeticInstruction(this); + visitor.visitLADD(this); + } + + public LADD() { + super((short) 97); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/LALOAD.java b/src/main/java/com/allatori/lib/bcel/generic/LALOAD.java new file mode 100644 index 0000000..dec0a29 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/LALOAD.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class LALOAD extends ArrayInstruction implements StackProducer { + + @Override + public void accept(Visitor visitor) { + visitor.visitStackProducer(this); + visitor.visitExceptionThrower(this); + visitor.visitTypedInstruction(this); + visitor.visitArrayInstruction(this); + visitor.visitLALOAD(this); + } + + public LALOAD() { + super((short) 47); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/LAND.java b/src/main/java/com/allatori/lib/bcel/generic/LAND.java new file mode 100644 index 0000000..d2d18d1 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/LAND.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class LAND extends ArithmeticInstruction { + + public LAND() { + super((short) 127); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitArithmeticInstruction(this); + visitor.visitLAND(this); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/LASTORE.java b/src/main/java/com/allatori/lib/bcel/generic/LASTORE.java new file mode 100644 index 0000000..8470cc2 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/LASTORE.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class LASTORE extends ArrayInstruction implements StackConsumer { + + @Override + public void accept(Visitor visitor) { + visitor.visitStackConsumer(this); + visitor.visitExceptionThrower(this); + visitor.visitTypedInstruction(this); + visitor.visitArrayInstruction(this); + visitor.visitLASTORE(this); + } + + public LASTORE() { + super((short) 80); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/LCMP.java b/src/main/java/com/allatori/lib/bcel/generic/LCMP.java new file mode 100644 index 0000000..6e2f671 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/LCMP.java @@ -0,0 +1,21 @@ +package com.allatori.lib.bcel.generic; + +public class LCMP extends Instruction implements TypedInstruction, StackProducer, StackConsumer { + + public LCMP() { + super((short) 148, (short) 1); + } + + @Override + public Type getType(ConstantPoolGen constantPoolGen) { + return Type.LONG; + } + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitLCMP(this); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/LCONST.java b/src/main/java/com/allatori/lib/bcel/generic/LCONST.java new file mode 100644 index 0000000..ef33bb3 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/LCONST.java @@ -0,0 +1,43 @@ +package com.allatori.lib.bcel.generic; + +public class LCONST extends Instruction implements ConstantPushInstruction, TypedInstruction { + + public long value; + + public LCONST() {} + + @Override + public Type getType(ConstantPoolGen constantPoolGen) { + return Type.LONG; + } + + @Override + public void accept(Visitor visitor) { + visitor.visitPushInstruction(this); + visitor.visitStackProducer(this); + visitor.visitTypedInstruction(this); + visitor.visitConstantPushInstruction(this); + visitor.visitLCONST(this); + } + + public LCONST(long value2) { + super((short) 9, (short) 1); + LCONST lCONST; + if (value2 == 0L) { + lCONST = this; + this.opcode = 9; + } else { + if (value2 != 1L) { + throw new ClassGenException(("LCONST can be used only for 0 and 1: " + value2)); + } + lCONST = this; + this.opcode = 10; + } + lCONST.value = value2; + } + + @Override + public Number getValue() { + return new Long(this.value); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/LDC.java b/src/main/java/com/allatori/lib/bcel/generic/LDC.java new file mode 100644 index 0000000..7d4cb6c --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/LDC.java @@ -0,0 +1,107 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.ExceptionConstants; +import com.allatori.lib.bcel.classfile.Constant; +import com.allatori.lib.bcel.classfile.ConstantFloat; +import com.allatori.lib.bcel.classfile.ConstantInteger; +import com.allatori.lib.bcel.classfile.ConstantString; +import com.allatori.lib.bcel.classfile.ConstantUtf8; +import com.allatori.lib.bcel.util.ByteSequence; +import java.io.DataOutputStream; +import java.io.IOException; + +public class LDC extends CPInstruction + implements PushInstruction, ExceptionThrower, TypedInstruction { + + public LDC(int value) { + super((short) 19, value); + this.setSize(); + } + + @Override + public void initFromFile(ByteSequence byteSequence, boolean matches) throws IOException { + this.length = 2; + this.index = byteSequence.readUnsignedByte(); + } + + @Override + public final void setIndex(int value) { + super.setIndex(value); + this.setSize(); + } + + @Override + public Class[] getExceptions() { + return ExceptionConstants.TYPES; + } + + public final void setSize() { + if (this.index <= 255) { + this.opcode = 18; + this.length = 2; + } else { + this.opcode = 19; + this.length = 3; + } + } + + public LDC() {} + + @Override + public void accept(Visitor visitor) { + visitor.visitStackProducer(this); + visitor.visitPushInstruction(this); + visitor.visitExceptionThrower(this); + visitor.visitTypedInstruction(this); + visitor.visitCPInstruction(this); + visitor.visitLDC(this); + } + + @Override + public Type getType(ConstantPoolGen constantPoolGen) { + switch (constantPoolGen.getConstantPool().getConstant(this.index).getTag()) { + case 3: + return Type.INT; + case 4: + return Type.FLOAT; + case 5: + case 6: + default: + throw new RuntimeException(("Unknown or invalid constant type at " + this.index)); + case 7: + return Type.CLASS; + case 8: + return Type.STRING; + } + } + + public Object getValue(ConstantPoolGen constantPoolGen) { + Constant constant; + switch ((constant = constantPoolGen.getConstantPool().getConstant(this.index)).getTag()) { + case 3: + return new Integer(((ConstantInteger) constant).getBytes()); + case 4: + return new Float(((ConstantFloat) constant).getBytes()); + case 5: + case 6: + default: + throw new RuntimeException(("Unknown or invalid constant type at " + this.index)); + case 7: + return constant; + case 8: + int stringIndex = ((ConstantString) constant).getStringIndex(); + return ((ConstantUtf8) constantPoolGen.getConstantPool().getConstant(stringIndex)) + .getBytes(); + } + } + + @Override + public void dump(DataOutputStream dataOutputStream) throws IOException { + dataOutputStream.writeByte(this.opcode); + if (this.length == 2) { + dataOutputStream.writeByte(this.index); + } else { + dataOutputStream.writeShort(this.index); + } + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/LDC2_W.java b/src/main/java/com/allatori/lib/bcel/generic/LDC2_W.java new file mode 100644 index 0000000..96d144f --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/LDC2_W.java @@ -0,0 +1,47 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.classfile.Constant; +import com.allatori.lib.bcel.classfile.ConstantDouble; +import com.allatori.lib.bcel.classfile.ConstantLong; + +public class LDC2_W extends CPInstruction implements PushInstruction, TypedInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitStackProducer(this); + visitor.visitPushInstruction(this); + visitor.visitTypedInstruction(this); + visitor.visitCPInstruction(this); + visitor.visitLDC2_W(this); + } + + @Override + public Type getType(ConstantPoolGen constantPoolGen) { + switch (constantPoolGen.getConstantPool().getConstant(this.index).getTag()) { + case 5: + return Type.LONG; + case 6: + return Type.DOUBLE; + default: + throw new RuntimeException(("Unknown constant type " + this.opcode)); + } + } + + public Number getValue(ConstantPoolGen constantPoolGen) { + Constant constant; + switch ((constant = constantPoolGen.getConstantPool().getConstant(this.index)).getTag()) { + case 5: + return new Long(((ConstantLong) constant).getBytes()); + case 6: + return new Double(((ConstantDouble) constant).getBytes()); + default: + throw new RuntimeException(("Unknown or invalid constant type at " + this.index)); + } + } + + public LDC2_W(int value) { + super((short) 20, value); + } + + public LDC2_W() {} +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/LDC_W.java b/src/main/java/com/allatori/lib/bcel/generic/LDC_W.java new file mode 100644 index 0000000..6bf3f62 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/LDC_W.java @@ -0,0 +1,20 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.util.ByteSequence; +import java.io.IOException; + +public class LDC_W extends LDC { + + @Override + public void initFromFile(ByteSequence byteSequence, boolean matches) throws IOException { + this.setIndex(byteSequence.readUnsignedShort()); + this.opcode = 19; + this.length = 3; + } + + public LDC_W() {} + + public LDC_W(int value) { + super(value); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/LDIV.java b/src/main/java/com/allatori/lib/bcel/generic/LDIV.java new file mode 100644 index 0000000..b0356ff --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/LDIV.java @@ -0,0 +1,25 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.ExceptionConstants; + +public class LDIV extends ArithmeticInstruction implements ExceptionThrower { + + public LDIV() { + super((short) 109); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitExceptionThrower(this); + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitArithmeticInstruction(this); + visitor.visitLDIV(this); + } + + @Override + public Class[] getExceptions() { + return new Class[] {ExceptionConstants.TYPE18}; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/LLOAD.java b/src/main/java/com/allatori/lib/bcel/generic/LLOAD.java new file mode 100644 index 0000000..696c3d5 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/LLOAD.java @@ -0,0 +1,18 @@ +package com.allatori.lib.bcel.generic; + +public class LLOAD extends LoadInstruction { + + public LLOAD() { + super((short) 22, (short) 30); + } + + @Override + public void accept(Visitor visitor) { + super.accept(visitor); + visitor.visitLLOAD(this); + } + + public LLOAD(int value) { + super((short) 22, (short) 30, value); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/LMUL.java b/src/main/java/com/allatori/lib/bcel/generic/LMUL.java new file mode 100644 index 0000000..b0cff2c --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/LMUL.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class LMUL extends ArithmeticInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitArithmeticInstruction(this); + visitor.visitLMUL(this); + } + + public LMUL() { + super((short) 105); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/LNEG.java b/src/main/java/com/allatori/lib/bcel/generic/LNEG.java new file mode 100644 index 0000000..7a6733a --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/LNEG.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class LNEG extends ArithmeticInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitArithmeticInstruction(this); + visitor.visitLNEG(this); + } + + public LNEG() { + super((short) 117); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/LOOKUPSWITCH.java b/src/main/java/com/allatori/lib/bcel/generic/LOOKUPSWITCH.java new file mode 100644 index 0000000..f39a8e2 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/LOOKUPSWITCH.java @@ -0,0 +1,63 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.util.ByteSequence; +import java.io.DataOutputStream; +import java.io.IOException; + +public class LOOKUPSWITCH extends Select { + + public LOOKUPSWITCH() {} + + @Override + public void dump(DataOutputStream dataOutputStream) throws IOException { + int value = 0; + super.dump(dataOutputStream); + dataOutputStream.writeInt(this.match_length); + for (int index = 0; value < this.match_length; value = index) { + dataOutputStream.writeInt(this.match[index]); + int[] values = this.indices; + int value2; + int value3 = value2 = this.getTargetOffset(this.targets[index]); + int value4 = index; + index++; + values[value4] = value2; + dataOutputStream.writeInt(value3); + } + } + + @Override + public void accept(Visitor visitor) { + visitor.visitVariableLengthInstruction(this); + visitor.visitStackProducer(this); + visitor.visitBranchInstruction(this); + visitor.visitSelect(this); + visitor.visitLOOKUPSWITCH(this); + } + + @Override + public void initFromFile(ByteSequence byteSequence, boolean matches) throws IOException { + super.initFromFile(byteSequence, matches); + this.match_length = byteSequence.readInt(); + this.fixed_length = (short) (9 + this.match_length * 8); + this.length = (short) (this.fixed_length + this.padding); + this.match = new int[this.match_length]; + this.indices = new int[this.match_length]; + this.targets = new InstructionHandle[this.match_length]; + int value; + for (int value2 = value = 0; value2 < this.match_length; value2 = value) { + this.match[value] = byteSequence.readInt(); + int[] values = this.indices; + int value3 = byteSequence.readInt(); + int value4 = value; + value++; + values[value4] = value3; + } + } + + public LOOKUPSWITCH( + int[] values, InstructionHandle[] instructionHandles, InstructionHandle instructionHandle) { + super((short) 171, values, instructionHandles, instructionHandle); + this.length = (short) (9 + this.match_length * 8); + this.fixed_length = this.length; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/LOR.java b/src/main/java/com/allatori/lib/bcel/generic/LOR.java new file mode 100644 index 0000000..c48c178 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/LOR.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class LOR extends ArithmeticInstruction { + + public LOR() { + super((short) 129); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitArithmeticInstruction(this); + visitor.visitLOR(this); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/LREM.java b/src/main/java/com/allatori/lib/bcel/generic/LREM.java new file mode 100644 index 0000000..a388710 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/LREM.java @@ -0,0 +1,25 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.ExceptionConstants; + +public class LREM extends ArithmeticInstruction implements ExceptionThrower { + + public LREM() { + super((short) 113); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitExceptionThrower(this); + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitArithmeticInstruction(this); + visitor.visitLREM(this); + } + + @Override + public Class[] getExceptions() { + return new Class[] {ExceptionConstants.TYPE18}; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/LRETURN.java b/src/main/java/com/allatori/lib/bcel/generic/LRETURN.java new file mode 100644 index 0000000..695891d --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/LRETURN.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class LRETURN extends ReturnInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitExceptionThrower(this); + visitor.visitTypedInstruction(this); + visitor.visitStackConsumer(this); + visitor.visitReturnInstruction(this); + visitor.visitLRETURN(this); + } + + public LRETURN() { + super((short) 173); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/LSHL.java b/src/main/java/com/allatori/lib/bcel/generic/LSHL.java new file mode 100644 index 0000000..df4356f --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/LSHL.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class LSHL extends ArithmeticInstruction { + + public LSHL() { + super((short) 121); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitArithmeticInstruction(this); + visitor.visitLSHL(this); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/LSHR.java b/src/main/java/com/allatori/lib/bcel/generic/LSHR.java new file mode 100644 index 0000000..43660d6 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/LSHR.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class LSHR extends ArithmeticInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitArithmeticInstruction(this); + visitor.visitLSHR(this); + } + + public LSHR() { + super((short) 123); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/LSTORE.java b/src/main/java/com/allatori/lib/bcel/generic/LSTORE.java new file mode 100644 index 0000000..b93e151 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/LSTORE.java @@ -0,0 +1,18 @@ +package com.allatori.lib.bcel.generic; + +public class LSTORE extends StoreInstruction { + + @Override + public void accept(Visitor visitor) { + super.accept(visitor); + visitor.visitLSTORE(this); + } + + public LSTORE(int value) { + super((short) 55, (short) 63, value); + } + + public LSTORE() { + super((short) 55, (short) 63); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/LSUB.java b/src/main/java/com/allatori/lib/bcel/generic/LSUB.java new file mode 100644 index 0000000..7c20cf6 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/LSUB.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class LSUB extends ArithmeticInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitArithmeticInstruction(this); + visitor.visitLSUB(this); + } + + public LSUB() { + super((short) 101); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/LUSHR.java b/src/main/java/com/allatori/lib/bcel/generic/LUSHR.java new file mode 100644 index 0000000..838080e --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/LUSHR.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class LUSHR extends ArithmeticInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitArithmeticInstruction(this); + visitor.visitLUSHR(this); + } + + public LUSHR() { + super((short) 125); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/LXOR.java b/src/main/java/com/allatori/lib/bcel/generic/LXOR.java new file mode 100644 index 0000000..7b7b6d6 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/LXOR.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class LXOR extends ArithmeticInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitTypedInstruction(this); + visitor.visitStackProducer(this); + visitor.visitStackConsumer(this); + visitor.visitArithmeticInstruction(this); + visitor.visitLXOR(this); + } + + public LXOR() { + super((short) 131); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/LineNumberGen.java b/src/main/java/com/allatori/lib/bcel/generic/LineNumberGen.java new file mode 100644 index 0000000..cbdda01 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/LineNumberGen.java @@ -0,0 +1,63 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.classfile.LineNumber; +import java.io.Serializable; + +public class LineNumberGen implements InstructionTargeter, Cloneable, Serializable { + + public InstructionHandle ih; + + public int src_line; + + @Override + public Object clone() { + try { + return super.clone(); + } catch (CloneNotSupportedException cloneNotSupportedException) { + System.err.println(cloneNotSupportedException); + return null; + } + } + + public InstructionHandle getInstruction() { + return this.ih; + } + + public LineNumber getLineNumber() { + return new LineNumber(this.ih.getPosition(), this.src_line); + } + + public int getSourceLine() { + return this.src_line; + } + + @Override + public void updateTarget( + InstructionHandle instructionHandle, InstructionHandle instructionHandle2) { + if (instructionHandle != this.ih) { + throw new ClassGenException( + ("Not targeting " + instructionHandle + ", but " + this.ih + "}")); + } + this.setInstruction(instructionHandle2); + } + + public void setInstruction(InstructionHandle instructionHandle) { + BranchInstruction.notifyTarget(this.ih, instructionHandle, this); + this.ih = instructionHandle; + } + + public LineNumberGen(InstructionHandle instructionHandle, int value) { + super(); + this.setInstruction(instructionHandle); + this.setSourceLine(value); + } + + @Override + public boolean containsTarget(InstructionHandle instructionHandle) { + return this.ih == instructionHandle; + } + + public void setSourceLine(int src_line) { + this.src_line = src_line; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/LoadClass.java b/src/main/java/com/allatori/lib/bcel/generic/LoadClass.java new file mode 100644 index 0000000..3c91773 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/LoadClass.java @@ -0,0 +1,8 @@ +package com.allatori.lib.bcel.generic; + +public interface LoadClass { + + ObjectType getLoadClassType(ConstantPoolGen constantPoolGen); + + Type getType(ConstantPoolGen constantPoolGen); +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/LoadInstruction.java b/src/main/java/com/allatori/lib/bcel/generic/LoadInstruction.java new file mode 100644 index 0000000..b5bccc5 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/LoadInstruction.java @@ -0,0 +1,21 @@ +package com.allatori.lib.bcel.generic; + +public abstract class LoadInstruction extends LocalVariableInstruction implements PushInstruction { + + public LoadInstruction(short value, short value2, int value3) { + super(value, value2, value3); + } + + public LoadInstruction(short value, short value2) { + super(value, value2); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitStackProducer(this); + visitor.visitPushInstruction(this); + visitor.visitTypedInstruction(this); + visitor.visitLocalVariableInstruction(this); + visitor.visitLoadInstruction(this); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/LocalVariableGen.java b/src/main/java/com/allatori/lib/bcel/generic/LocalVariableGen.java new file mode 100644 index 0000000..bf3e863 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/LocalVariableGen.java @@ -0,0 +1,149 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.classfile.LocalVariable; +import java.io.Serializable; + +public class LocalVariableGen + implements InstructionTargeter, NamedAndTyped, Cloneable, Serializable { + + public InstructionHandle instructionHandle; + + public int index; + + public Type type; + + public String name; + + public InstructionHandle instructionHandle2; + + @Override + public String getName() { + return this.name; + } + + @Override + public Object clone() { + try { + return super.clone(); + } catch (CloneNotSupportedException cloneNotSupportedException) { + System.err.println(cloneNotSupportedException); + return null; + } + } + + public void setIndex(int index) { + this.index = index; + } + + @Override + public void updateTarget( + InstructionHandle instructionHandle3, InstructionHandle instructionHandle4) { + byte value = 0; + if (this.instructionHandle == instructionHandle3) { + value = 1; + this.processInstructionHandle2(instructionHandle4); + } + if (this.instructionHandle2 == instructionHandle3) { + value = 1; + this.processInstructionHandle(instructionHandle4); + } + if (value == 0) { + throw new ClassGenException( + ("Not targeting " + + instructionHandle3 + + ", but {" + + this.instructionHandle + + ", " + + this.instructionHandle2 + + "}")); + } + } + + @Override + public boolean equals(Object result) { + LocalVariableGen localVariableGen; + return !(result instanceof LocalVariableGen) + ? false + : (localVariableGen = (LocalVariableGen) result).index == this.index + && localVariableGen.instructionHandle == this.instructionHandle + && localVariableGen.instructionHandle2 == this.instructionHandle2; + } + + public int getIndex() { + return this.index; + } + + public InstructionHandle getInstructionHandle2() { + return this.instructionHandle2; + } + + @Override + public int hashCode() { + return this.index ^ this.name.hashCode() ^ this.type.hashCode(); + } + + public void processInstructionHandle(InstructionHandle instructionHandle) { + BranchInstruction.notifyTarget(this.instructionHandle2, instructionHandle, this); + this.instructionHandle2 = instructionHandle; + } + + public LocalVariable getLocalVariable(ConstantPoolGen constantPoolGen) { + int position = this.instructionHandle.getPosition(); + int value; + if ((value = this.instructionHandle2.getPosition() - position) > 0) { + value += this.instructionHandle2.getInstruction().getLength(); + } + int value2 = constantPoolGen.addUtf8(this.name); + int value3 = constantPoolGen.addUtf8(this.type.getSignature()); + return new LocalVariable( + position, value, value2, value3, this.index, constantPoolGen.getConstantPool()); + } + + public InstructionHandle getInstructionHandle() { + return this.instructionHandle; + } + + @Override + public void setName(String name) { + this.name = name; + } + + public void processInstructionHandle2(InstructionHandle instructionHandle2) { + BranchInstruction.notifyTarget(this.instructionHandle, instructionHandle2, this); + this.instructionHandle = instructionHandle2; + } + + public LocalVariableGen( + int index, + String name, + Type type2, + InstructionHandle instructionHandle, + InstructionHandle instructionHandle2) { + super(); + if (index >= 0 && index <= 65535) { + this.name = name; + this.type = type2; + this.index = index; + this.processInstructionHandle2(instructionHandle); + this.processInstructionHandle(instructionHandle2); + } else { + throw new ClassGenException(("Invalid index index: " + index)); + } + } + + @Override + public boolean containsTarget(InstructionHandle instructionHandle3) { + return this.instructionHandle == instructionHandle3 + || this.instructionHandle2 == instructionHandle3; + } + + @Override + public Type getType() { + return this.type; + } + + @Override + public void setType(Type type2) { + this.type = type2; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/LocalVariableInstruction.java b/src/main/java/com/allatori/lib/bcel/generic/LocalVariableInstruction.java new file mode 100644 index 0000000..046f51d --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/LocalVariableInstruction.java @@ -0,0 +1,164 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.util.ByteSequence; +import java.io.DataOutputStream; +import java.io.IOException; + +public abstract class LocalVariableInstruction extends Instruction + implements TypedInstruction, IndexedInstruction { + + public short c_tag; + + public int n = -1; + + public short canon_tag; + + public final boolean wide() { + return this.n > 255; + } + + @Override + public Type getType(ConstantPoolGen constantPoolGen) { + switch (this.canon_tag) { + case 21: + case 54: + return Type.INT; + case 22: + case 55: + return Type.LONG; + case 23: + case 56: + return Type.FLOAT; + case 24: + case 57: + return Type.DOUBLE; + case 25: + case 58: + return Type.OBJECT; + case 26: + case 27: + case 28: + case 29: + case 30: + case 31: + case 32: + case 33: + case 34: + case 35: + case 36: + case 37: + case 38: + case 39: + case 40: + case 41: + case 42: + case 43: + case 44: + case 45: + case 46: + case 47: + case 48: + case 49: + case 50: + case 51: + case 52: + case 53: + default: + throw new ClassGenException(("Oops: unknown case in switch" + this.canon_tag)); + } + } + + public short getCanonicalTag() { + return this.canon_tag; + } + + public LocalVariableInstruction() { + this.c_tag = -1; + this.canon_tag = -1; + } + + public LocalVariableInstruction(short canon_tag, short c_tag) { + super(); + this.n = -1; + this.c_tag = -1; + this.canon_tag = -1; + this.canon_tag = canon_tag; + this.c_tag = c_tag; + } + + @Override + public void dump(DataOutputStream dataOutputStream) throws IOException { + if (this.wide()) { + dataOutputStream.writeByte(196); + } + dataOutputStream.writeByte(this.opcode); + if (this.length > 1) { + if (this.wide()) { + dataOutputStream.writeShort(this.n); + return; + } + dataOutputStream.writeByte(this.n); + } + } + + @Override + public void initFromFile(ByteSequence byteSequence, boolean matches) throws IOException { + if (matches) { + this.n = byteSequence.readUnsignedShort(); + this.length = 4; + } else if ((this.opcode < 21 || this.opcode > 25) && (this.opcode < 54 || this.opcode > 58)) { + if (this.opcode <= 45) { + this.n = (this.opcode - 26) % 4; + this.length = 1; + } else { + this.n = (this.opcode - 59) % 4; + this.length = 1; + } + } else { + this.n = byteSequence.readUnsignedByte(); + this.length = 2; + } + } + + public LocalVariableInstruction(short canon_tag, short c_tag, int value3) { + super(canon_tag, (short) 2); + this.n = -1; + this.c_tag = -1; + this.canon_tag = -1; + this.c_tag = c_tag; + this.canon_tag = canon_tag; + this.setIndex(value3); + } + + @Override + public void setIndex(int n) { + if (n >= 0 && n <= 65535) { + this.n = n; + if (n >= 0 && n <= 3) { + this.opcode = (short) (this.c_tag + n); + this.length = 1; + } else { + this.opcode = this.canon_tag; + if (this.wide()) { + this.length = 4; + } else { + this.length = 2; + } + } + } else { + throw new ClassGenException(("Illegal value: " + n)); + } + } + + @Override + public final int getIndex() { + return this.n; + } + + @Override + public String toString(boolean matches) { + return (this.opcode < 26 || this.opcode > 45) && (this.opcode < 59 || this.opcode > 78) + ? ("" + super.toString(matches) + " " + this.n) + : super.toString(matches); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/MONITORENTER.java b/src/main/java/com/allatori/lib/bcel/generic/MONITORENTER.java new file mode 100644 index 0000000..44d57b7 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/MONITORENTER.java @@ -0,0 +1,22 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.ExceptionConstants; + +public class MONITORENTER extends Instruction implements ExceptionThrower, StackConsumer { + + @Override + public void accept(Visitor visitor) { + visitor.visitExceptionThrower(this); + visitor.visitStackConsumer(this); + visitor.visitMONITORENTER(this); + } + + @Override + public Class[] getExceptions() { + return new Class[] {ExceptionConstants.TYPE3}; + } + + public MONITORENTER() { + super((short) 194, (short) 1); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/MONITOREXIT.java b/src/main/java/com/allatori/lib/bcel/generic/MONITOREXIT.java new file mode 100644 index 0000000..f9b57da --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/MONITOREXIT.java @@ -0,0 +1,22 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.ExceptionConstants; + +public class MONITOREXIT extends Instruction implements ExceptionThrower, StackConsumer { + + public MONITOREXIT() { + super((short) 195, (short) 1); + } + + @Override + public Class[] getExceptions() { + return new Class[] {ExceptionConstants.TYPE3}; + } + + @Override + public void accept(Visitor visitor) { + visitor.visitExceptionThrower(this); + visitor.visitStackConsumer(this); + visitor.visitMONITOREXIT(this); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/MULTIANEWARRAY.java b/src/main/java/com/allatori/lib/bcel/generic/MULTIANEWARRAY.java new file mode 100644 index 0000000..6bf8219 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/MULTIANEWARRAY.java @@ -0,0 +1,85 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.ExceptionConstants; +import com.allatori.lib.bcel.classfile.ConstantPool; +import com.allatori.lib.bcel.util.ByteSequence; +import java.io.DataOutputStream; +import java.io.IOException; + +public class MULTIANEWARRAY extends CPInstruction + implements LoadClass, AllocationInstruction, ExceptionThrower { + + public short dimensions; + + @Override + public String toString(ConstantPool constantPool) { + return "" + super.toString(constantPool) + " " + this.dimensions; + } + + @Override + public void dump(DataOutputStream dataOutputStream) throws IOException { + dataOutputStream.writeByte(this.opcode); + dataOutputStream.writeShort(this.index); + dataOutputStream.writeByte(this.dimensions); + } + + @Override + public ObjectType getLoadClassType(ConstantPoolGen constantPoolGen) { + Type type; + if ((type = this.getType(constantPoolGen)) instanceof ArrayType) { + type = ((ArrayType) type).getBasicType(); + } + return type instanceof ObjectType ? (ObjectType) type : null; + } + + public final short getDimensions() { + return this.dimensions; + } + + @Override + public int consumeStack(ConstantPoolGen constantPoolGen) { + return this.dimensions; + } + + @Override + public void initFromFile(ByteSequence byteSequence, boolean matches) throws IOException { + super.initFromFile(byteSequence, matches); + this.dimensions = byteSequence.readByte(); + this.length = 4; + } + + public MULTIANEWARRAY() {} + + @Override + public String toString(boolean matches) { + return "" + super.toString(matches) + " " + this.index + " " + this.dimensions; + } + + @Override + public void accept(Visitor visitor) { + visitor.visitLoadClass(this); + visitor.visitAllocationInstruction(this); + visitor.visitExceptionThrower(this); + visitor.visitTypedInstruction(this); + visitor.visitCPInstruction(this); + visitor.visitMULTIANEWARRAY(this); + } + + @Override + public Class[] getExceptions() { + Class[] classs = new Class[2 + ExceptionConstants.TYPES5.length]; + System.arraycopy(ExceptionConstants.TYPES5, 0, classs, 0, ExceptionConstants.TYPES5.length); + classs[ExceptionConstants.TYPES5.length + 1] = ExceptionConstants.TYPE11; + classs[ExceptionConstants.TYPES5.length] = ExceptionConstants.TYPE7; + return classs; + } + + public MULTIANEWARRAY(int value, short dimensions) { + super((short) 197, value); + if (dimensions < 1) { + throw new ClassGenException(("Invalid dimensions value: " + dimensions)); + } + this.dimensions = dimensions; + this.length = 4; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/MethodGen$2.java b/src/main/java/com/allatori/lib/bcel/generic/MethodGen$2.java new file mode 100644 index 0000000..48bf5c7 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/MethodGen$2.java @@ -0,0 +1,25 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.bytecode.ClassHierarchy; +import java.util.Comparator; + +public class MethodGen$2 implements Comparator { + + public final ClassHierarchy classHierarchy; + + @Override + public int compare(Object result, Object result2) { + boolean enabled5 = ((ClassGen) result).isEnabled5(); + boolean enabled52 = ((ClassGen) result2).isEnabled5(); + if (enabled5 == enabled52) { + return 0; + } else { + return enabled5 ? -1 : 1; + } + } + + public MethodGen$2(ClassHierarchy classHierarchy2) { + super(); + this.classHierarchy = classHierarchy2; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/MethodGen$BranchStack.java b/src/main/java/com/allatori/lib/bcel/generic/MethodGen$BranchStack.java new file mode 100644 index 0000000..e336d2c --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/MethodGen$BranchStack.java @@ -0,0 +1,32 @@ +package com.allatori.lib.bcel.generic; + +import java.util.Hashtable; +import java.util.Stack; + +public final class MethodGen$BranchStack { + + public Stack branchTargets = new Stack(); + + public Hashtable visitedTargets = new Hashtable(); + + public final MethodGen$BranchTarget visit(InstructionHandle instructionHandle, int value) { + MethodGen$BranchTarget methodGen$BranchTarget = + new MethodGen$BranchTarget(instructionHandle, value); + this.visitedTargets.put(instructionHandle, methodGen$BranchTarget); + return methodGen$BranchTarget; + } + + public MethodGen$BranchTarget pop() { + return !this.branchTargets.empty() ? (MethodGen$BranchTarget) this.branchTargets.pop() : null; + } + + public final boolean visited(InstructionHandle instructionHandle) { + return this.visitedTargets.get(instructionHandle) != null; + } + + public void push(InstructionHandle instructionHandle, int value) { + if (!this.visited(instructionHandle)) { + this.branchTargets.push(this.visit(instructionHandle, value)); + } + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/MethodGen$BranchTarget.java b/src/main/java/com/allatori/lib/bcel/generic/MethodGen$BranchTarget.java new file mode 100644 index 0000000..9ade98e --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/MethodGen$BranchTarget.java @@ -0,0 +1,14 @@ +package com.allatori.lib.bcel.generic; + +public final class MethodGen$BranchTarget { + + public InstructionHandle target; + + public int stackDepth; + + public MethodGen$BranchTarget(InstructionHandle instructionHandle, int stackDepth) { + super(); + this.target = instructionHandle; + this.stackDepth = stackDepth; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/MethodGen.java b/src/main/java/com/allatori/lib/bcel/generic/MethodGen.java new file mode 100644 index 0000000..0d7caac --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/MethodGen.java @@ -0,0 +1,986 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.classfile.AnnotationEntry; +import com.allatori.lib.bcel.classfile.Annotations; +import com.allatori.lib.bcel.classfile.Attribute; +import com.allatori.lib.bcel.classfile.Code; +import com.allatori.lib.bcel.classfile.CodeException; +import com.allatori.lib.bcel.classfile.ExceptionTable; +import com.allatori.lib.bcel.classfile.LineNumber; +import com.allatori.lib.bcel.classfile.LineNumberTable; +import com.allatori.lib.bcel.classfile.LocalVariable; +import com.allatori.lib.bcel.classfile.LocalVariableTable; +import com.allatori.lib.bcel.classfile.Method; +import com.allatori.lib.bcel.classfile.ParameterAnnotationEntry; +import com.allatori.lib.bcel.classfile.ParameterAnnotations; +import com.allatori.lib.bcel.classfile.RuntimeVisibleParameterAnnotations; +import com.allatori.lib.bcel.classfile.Utility; +import com.allatori.lib.bcel.util.BCELComparator; +import com.allatori.lib.bcel.util.comparator.MethodGenComparator; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class MethodGen extends FieldGenOrMethodGen { + + public boolean strip_attributes; + + public List values; + + public List throws_vec; + + public InstructionList il; + + public List[] param_annotations; + + public int count; + + public String class_name; + + public List code_attrs_vec; + + public static BCELComparator bcelComparator = new MethodGenComparator(); + + public List variable_vec; + + public List line_number_vec; + + public String[] arg_names; + + public List exception_vec; + + public int count2; + + public boolean hasParameterAnnotations; + + public boolean haveUnpackedParameterAnnotations; + + public Type[] arg_types; + + public Type getArgumentType(int value) { + return this.arg_types[value]; + } + + public Type getReturnType() { + return this.getType(); + } + + public void addCodeAttribute(Attribute attribute) { + this.code_attrs_vec.add(attribute); + } + + public CodeException[] getCodeExceptions() { + int value; + CodeException[] codeExceptions = new CodeException[value = this.exception_vec.size()]; + try { + int value2 = 0; + while (value2 < value) { + CodeExceptionGen codeExceptionGen = (CodeExceptionGen) this.exception_vec.get(value2); + CodeException codeException = codeExceptionGen.getCodeException(this.cp); + int value3 = value2; + value2++; + codeExceptions[value3] = codeException; + } + } catch (ArrayIndexOutOfBoundsException arrayIndexOutOfBoundsException) { + } + return codeExceptions; + } + + public ExceptionTable getExceptionTable(ConstantPoolGen constantPoolGen) { + int value; + int[] values = new int[value = this.throws_vec.size()]; + try { + int value2 = 0; + while (value2 < value) { + int value3 = constantPoolGen.addClass((String) this.throws_vec.get(value2)); + int value4 = value2; + value2++; + values[value4] = value3; + } + } catch (ArrayIndexOutOfBoundsException arrayIndexOutOfBoundsException) { + } + return new ExceptionTable( + constantPoolGen.addUtf8("Exceptions"), + 2 + 2 * value, + values, + constantPoolGen.getConstantPool()); + } + + public void setArgumentType(int value, Type type) { + this.arg_types[value] = type; + } + + public static int getMaxStack( + ConstantPoolGen constantPoolGen, + InstructionList instructionList, + CodeExceptionGen[] codeExceptionGens) { + MethodGen$BranchStack methodGen$BranchStack = new MethodGen$BranchStack(); + int value; + for (int value2 = value = 0; value2 < codeExceptionGens.length; value2 = ++value) { + InstructionHandle instructionHandle; + if ((instructionHandle = codeExceptionGens[value].getInstructionHandle3()) != null) { + methodGen$BranchStack.push(instructionHandle, 1); + } + } + int value3 = 0; + int value4 = 0; + InstructionHandle start = instructionList.getStart(); + while (start != null) { + Instruction instruction = start.getInstruction(); + short opcode = instruction.getOpcode(); + int value5 = + instruction.produceStack(constantPoolGen) - instruction.consumeStack(constantPoolGen); + if ((value3 += value5) > value4) { + value4 = value3; + } + InstructionHandle instructionHandle2; + if (instruction instanceof BranchInstruction) { + BranchInstruction branchInstruction = (BranchInstruction) instruction; + MethodGen$BranchStack methodGen$BranchStack2; + if (instruction instanceof Select) { + InstructionHandle[] targets = ((Select) branchInstruction).getTargets(); + int value6; + for (int value7 = value6 = 0; value7 < targets.length; value7 = value6) { + int value8 = value6; + value6++; + methodGen$BranchStack.push(targets[value8], value3); + } + start = null; + methodGen$BranchStack2 = methodGen$BranchStack; + } else { + if (!(branchInstruction instanceof IfInstruction)) { + if (opcode == 168 || opcode == 201) { + methodGen$BranchStack.push(start.getInstructionHandle2(), value3 - 1); + } + start = null; + } + methodGen$BranchStack2 = methodGen$BranchStack; + } + methodGen$BranchStack2.push(branchInstruction.getTarget(), value3); + instructionHandle2 = start; + } else { + if (opcode == 191 || opcode == 169 || opcode >= 172 && opcode <= 177) { + start = null; + } + instructionHandle2 = start; + } + if (instructionHandle2 != null) { + start = start.getInstructionHandle2(); + } + MethodGen$BranchTarget methodGen$BranchTarget; + if (start == null && (methodGen$BranchTarget = methodGen$BranchStack.pop()) != null) { + start = methodGen$BranchTarget.target; + value3 = methodGen$BranchTarget.stackDepth; + } + } + return value4; + } + + public MethodGen( + int value, + Type type, + Type[] types, + String[] texts, + String text, + String text2, + InstructionList instructionList, + ConstantPoolGen constantPoolGen) { + super(); + this.variable_vec = new ArrayList(); + this.line_number_vec = new ArrayList(); + this.exception_vec = new ArrayList(); + this.throws_vec = new ArrayList(); + this.code_attrs_vec = new ArrayList(); + this.hasParameterAnnotations = false; + this.haveUnpackedParameterAnnotations = false; + this.setAccess_flags(value); + this.setType(type); + this.setArgumentTypes(types); + this.setArgumentNames(texts); + this.setName(text); + this.setClassName(text2); + this.setInstructionList(instructionList); + this.setConstantPool(constantPoolGen); + boolean matches = this.isEnabled15() || this.isEnabled14(); + InstructionHandle instructionHandle = null; + InstructionHandle instructionHandle2 = null; + if (!matches) { + instructionHandle = instructionList.getStart(); + instructionHandle2 = instructionList.getEnd(); + if (!this.isEnabled11() && text2 != null) { + this.addLocalVariable("this", new ObjectType(text2), instructionHandle, instructionHandle2); + } + } + if (types != null) { + int value2 = types.length; + int value3; + for (int value4 = value3 = 0; value4 < value2; value4 = ++value3) { + if (Type.VOID == types[value3]) { + throw new ClassGenException("'void' is an illegal argument type for a method"); + } + } + if (texts != null) { + if (value2 != texts.length) { + throw new ClassGenException( + ("Mismatch in argument array lengths: " + value2 + " vs. " + texts.length)); + } + } else { + texts = new String[value2]; + int value5; + for (int value6 = value5 = 0; value6 < value2; value6 = value5) { + String text3 = "arg" + value5; + int value7 = value5; + String[] texts2 = texts; + value5++; + texts2[value7] = text3; + } + this.setArgumentNames(texts); + } + int value8; + if (!matches) { + for (int value9 = value8 = 0; value9 < value2; value9 = value8) { + String text4 = texts[value8]; + Type type2 = types[value8]; + value8++; + this.addLocalVariable(text4, type2, instructionHandle, instructionHandle2); + } + } + } + } + + public void stripAttributes(boolean strip_attributes) { + this.strip_attributes = strip_attributes; + } + + public static void setComparator(BCELComparator bCELComparator) { + bcelComparator = bCELComparator; + } + + public LineNumberGen addLineNumber(InstructionHandle instructionHandle, int value) { + LineNumberGen lineNumberGen = new LineNumberGen(instructionHandle, value); + this.line_number_vec.add(lineNumberGen); + return lineNumberGen; + } + + public List getAnnotationsOnParameter(int value) { + this.update2(); + return this.hasParameterAnnotations && value <= this.arg_types.length + ? this.param_annotations[value] + : null; + } + + public void setCount(int count) { + this.count = count; + } + + public static BCELComparator getComparator() { + return bcelComparator; + } + + public String[] getArgumentNames() { + return (String[]) this.arg_names.clone(); + } + + public void update() { + Iterator iterator2; + if (this.values != null) { + for (Iterator iterator3 = iterator2 = this.values.iterator(); + iterator3.hasNext(); + iterator3 = iterator2) { + ((MethodObserver) iterator2.next()).notify(this); + } + } + } + + public void removeLocalVariable(LocalVariableGen localVariableGen) { + this.variable_vec.remove(localVariableGen); + } + + public void update2() { + if (!this.haveUnpackedParameterAnnotations) { + Attribute[] attributes = this.getAttributes(); + ParameterAnnotations parameterAnnotations = null; + ParameterAnnotations parameterAnnotations2 = null; + int value; + for (int value2 = value = 0; value2 < attributes.length; value2 = ++value) { + Attribute attribute; + if ((attribute = attributes[value]) instanceof ParameterAnnotations) { + if (!this.hasParameterAnnotations) { + this.param_annotations = new List[this.arg_types.length]; + int value3; + for (int value4 = value3 = 0; value4 < this.arg_types.length; value4 = value3) { + List[] valuess = this.param_annotations; + ArrayList values = new ArrayList(); + int value5 = value3; + value3++; + valuess[value5] = values; + } + } + this.hasParameterAnnotations = true; + ParameterAnnotations parameterAnnotations3; + if ((parameterAnnotations3 = (ParameterAnnotations) attribute) + instanceof RuntimeVisibleParameterAnnotations) { + parameterAnnotations = parameterAnnotations3; + } else { + parameterAnnotations2 = parameterAnnotations3; + } + int value6; + for (int value7 = value6 = 0; value7 < this.arg_types.length; value7 = ++value6) { + try { + ParameterAnnotationEntry parameterAnnotationEntry = + parameterAnnotations3.getParameter_annotation_table()[value6]; + List values2 = + this.makeMutableVersion(parameterAnnotationEntry.getAnnotationEntries()); + this.param_annotations[value6].addAll(values2); + } catch (Exception exception) { + } + } + } + } + if (parameterAnnotations != null) { + this.removeAttribute(parameterAnnotations); + } + if (parameterAnnotations2 != null) { + this.removeAttribute(parameterAnnotations2); + } + this.haveUnpackedParameterAnnotations = true; + } + } + + public void removeExceptionHandlers() { + this.exception_vec.clear(); + } + + public int getCount() { + return this.count; + } + + public LocalVariableGen addLocalVariable( + String text, + Type type, + InstructionHandle instructionHandle, + InstructionHandle instructionHandle2) { + return this.addLocalVariable(text, type, this.count, instructionHandle, instructionHandle2); + } + + public void setInstructionList(InstructionList instructionList) { + this.il = instructionList; + } + + public void setArgumentName(int value, String text) { + this.arg_names[value] = text; + } + + @Override + public int hashCode() { + return bcelComparator.hashCode(this); + } + + public String[] getExceptions() { + String[] texts = new String[this.throws_vec.size()]; + this.throws_vec.toArray(texts); + return texts; + } + + public MethodGen copy(String text, ConstantPoolGen constantPoolGen) { + Method method = ((MethodGen) this.clone()).getMethod(); + MethodGen methodGen = new MethodGen(method, text, this.cp); + if (this.cp != constantPoolGen) { + methodGen.setConstantPool(constantPoolGen); + methodGen.getInstructionList().replaceConstantPool(this.cp, constantPoolGen); + } + return methodGen; + } + + public void removeLineNumbers() { + this.line_number_vec.clear(); + } + + public CodeExceptionGen addExceptionHandler( + InstructionHandle instructionHandle, + InstructionHandle instructionHandle2, + InstructionHandle instructionHandle3, + ObjectType objectType) { + if (instructionHandle != null && instructionHandle2 != null && instructionHandle3 != null) { + CodeExceptionGen codeExceptionGen = + new CodeExceptionGen( + instructionHandle, instructionHandle2, instructionHandle3, objectType); + this.exception_vec.add(codeExceptionGen); + return codeExceptionGen; + } else { + throw new ClassGenException("Exception handler target is null instruction"); + } + } + + public LocalVariableGen addLocalVariable( + String text, + Type type, + int value, + InstructionHandle instructionHandle, + InstructionHandle instructionHandle2) { + if (type.getType() != 16) { + int size = type.getSize(); + if (value + size > this.count) { + this.count = value + size; + } + LocalVariableGen localVariableGen = + new LocalVariableGen(value, text, type, instructionHandle, instructionHandle2); + int value2; + if ((value2 = this.variable_vec.indexOf(localVariableGen)) >= 0) { + this.variable_vec.set(value2, localVariableGen); + return localVariableGen; + } else { + this.variable_vec.add(localVariableGen); + return localVariableGen; + } + } else { + throw new IllegalArgumentException(("Can not use " + type + " as type for local variable")); + } + } + + public void getVariable_vec() { + this.variable_vec.clear(); + } + + public LocalVariableTable getLocalVariableTable(ConstantPoolGen constantPoolGen) { + int value; + LocalVariableGen[] localVariableGens; + LocalVariable[] localVariables = + new LocalVariable[value = (localVariableGens = this.getLocalVariables()).length]; + int value2; + for (int value3 = value2 = 0; value3 < value; value3 = value2) { + LocalVariable localVariable = localVariableGens[value2].getLocalVariable(constantPoolGen); + int value4 = value2; + value2++; + localVariables[value4] = localVariable; + } + return new LocalVariableTable( + constantPoolGen.addUtf8("LocalVariableTable"), + 2 + localVariables.length * 10, + localVariables, + constantPoolGen.getConstantPool()); + } + + public LineNumberTable getLineNumberTable(ConstantPoolGen constantPoolGen) { + int value; + LineNumber[] lineNumbers = new LineNumber[value = this.line_number_vec.size()]; + try { + int value2 = 0; + while (value2 < value) { + LineNumber lineNumber = ((LineNumberGen) this.line_number_vec.get(value2)).getLineNumber(); + int value3 = value2; + value2++; + lineNumbers[value3] = lineNumber; + } + } catch (ArrayIndexOutOfBoundsException arrayIndexOutOfBoundsException) { + } + return new LineNumberTable( + constantPoolGen.addUtf8("LineNumberTable"), + 2 + lineNumbers.length * 4, + lineNumbers, + constantPoolGen.getConstantPool()); + } + + public InstructionList getInstructionList() { + return this.il; + } + + public void removeExceptions() { + this.throws_vec.clear(); + } + + public void removeCodeAttributes() { + this.code_attrs_vec.clear(); + } + + public void update3() { + InstructionHandle instructionHandle; + if (this.il != null) { + for (InstructionHandle instructionHandle3 = instructionHandle = this.il.getStart(); + instructionHandle3 != null; + instructionHandle3 = instructionHandle) { + label42: + { + InstructionHandle instructionHandle4; + instructionHandle4 = instructionHandle.instructionHandle2; + label41: + if (instructionHandle.instructionHandle2 != null + && instructionHandle.getInstruction() instanceof NOP) { + try { + this.il.processInstructionHandle2(instructionHandle); + } catch (TargetLostException targetLostException) { + InstructionHandle[] targets = targetLostException.getTargets(); + int value; + int value2 = value = 0; + while (true) { + if (value2 >= targets.length) { + break label41; + } + InstructionTargeter[] targeters = targets[value].getTargeters(); + int value3; + for (int value4 = value3 = 0; value4 < targeters.length; value4 = value3) { + InstructionTargeter instructionTargeter = targeters[value3]; + int value5 = value; + value3++; + instructionTargeter.updateTarget(targets[value5], instructionHandle4); + } + value2 = ++value; + } + } + instructionHandle3 = instructionHandle4; + break label42; + } + instructionHandle3 = instructionHandle4; + } + instructionHandle = instructionHandle3; + } + } + } + + public void update4() { + if (this.il != null) { + int value = this.isEnabled11() ? 0 : 1; + int value2; + if (this.arg_types != null) { + for (int value3 = value2 = 0; value3 < this.arg_types.length; value3 = value2) { + Type type = this.arg_types[value2]; + int value4 = value; + value2++; + value = value4 + type.getSize(); + } + } + InstructionHandle instructionHandle; + for (InstructionHandle instructionHandle2 = instructionHandle = this.il.getStart(); + instructionHandle2 != null; + instructionHandle2 = instructionHandle = instructionHandle.getInstructionHandle2()) { + int value5; + Instruction instruction; + if (((instruction = instructionHandle.getInstruction()) instanceof LocalVariableInstruction + || instruction instanceof RET + || instruction instanceof IINC) + && (value5 = + ((IndexedInstruction) instruction).getIndex() + + ((TypedInstruction) instruction).getType(this.cp).getSize()) + > value) { + value = value5; + } + } + this.count = value; + } else { + this.count = 0; + } + } + + public String getArgumentName(int value) { + return this.arg_names[value]; + } + + public void removeCodeAttribute(Attribute attribute) { + this.code_attrs_vec.remove(attribute); + } + + public void addParameterAnnotation(int value, AnnotationEntryGen annotationEntryGen) { + this.update2(); + if (!this.hasParameterAnnotations) { + this.param_annotations = new List[this.arg_types.length]; + this.hasParameterAnnotations = true; + } + List values; + if ((values = this.param_annotations[value]) != null) { + values.add(annotationEntryGen); + } else { + ArrayList values2; + (values2 = new ArrayList()).add(annotationEntryGen); + this.param_annotations[value] = values2; + } + } + + public void setArgumentTypes(Type[] types) { + this.arg_types = types; + } + + public void addException(String text) { + this.throws_vec.add(text); + } + + public void processMethodObserver(MethodObserver methodObserver) { + if (this.values == null) { + this.values = new ArrayList(); + } + this.values.add(methodObserver); + } + + public String getClass_name() { + return this.class_name; + } + + public CodeExceptionGen[] getExceptionHandlers() { + CodeExceptionGen[] codeExceptionGens = new CodeExceptionGen[this.exception_vec.size()]; + this.exception_vec.toArray(codeExceptionGens); + return codeExceptionGens; + } + + @Override + public String getText() { + return Type.getMethodSignature(this.type, this.arg_types); + } + + public void setArgumentNames(String[] texts) { + this.arg_names = texts; + } + + public Attribute[] getCodeAttributes() { + Attribute[] attributes = new Attribute[this.code_attrs_vec.size()]; + this.code_attrs_vec.toArray(attributes); + return attributes; + } + + public void setClassName(String class_name) { + this.class_name = class_name; + } + + public MethodGen(Method method, String text, ConstantPoolGen constantPoolGen) { + this( + method.getAccess_flags2(), + Type.getReturnType(method.getText2()), + Type.getArgumentTypes(method.getText2()), + null, + method.getText(), + text, + (method.getAccess_flags2() & 1280) == 0 + ? new InstructionList(method.getCode().getCode()) + : null, + constantPoolGen); + Type type; + Attribute[] attributes = method.getAttributes(); + int value; + for (int value2 = value = 0; value2 < attributes.length; value2 = ++value) { + Attribute attribute; + if (!((attribute = attributes[value]) instanceof Code)) { + if (attribute instanceof ExceptionTable) { + String[] exceptionNames = ((ExceptionTable) attribute).getExceptionNames(); + int value3; + for (int value4 = value3 = 0; value4 < exceptionNames.length; value4 = value3) { + int value5 = value3; + value3++; + this.addException(exceptionNames[value5]); + } + } else if (attribute instanceof Annotations) { + AnnotationEntry[] annotationEntries = ((Annotations) attribute).getAnnotationEntries(); + int value6; + for (int value7 = value6 = 0; value7 < annotationEntries.length; value7 = value6) { + AnnotationEntry annotationEntry = annotationEntries[value6]; + value6++; + this.processAnnotationEntryGen( + new AnnotationEntryGen(annotationEntry, constantPoolGen, false)); + } + } else { + this.addAttribute(attribute); + } + } else { + Code code = (Code) attribute; + this.setCount2(code.getMax_stack()); + this.setCount(code.getMax_locals()); + int value8; + CodeException[] codeExceptions; + if ((codeExceptions = code.getExceptionTable()) != null) { + for (int value9 = value8 = 0; value9 < codeExceptions.length; value9 = value8) { + CodeException codeException; + int catch_type = (codeException = codeExceptions[value8]).getCatch_type(); + ObjectType objectType = null; + if (catch_type > 0) { + String text2 = method.getConstantPool().createText(catch_type, (byte) 7); + objectType = new ObjectType(text2); + } + int end_pc = codeException.getEnd_pc(); + InstructionHandle instructionHandle; + MethodGen methodGen; + if (method.getCode().getCode().length == end_pc) { + methodGen = this; + instructionHandle = this.il.getEnd(); + } else { + methodGen = this; + instructionHandle = this.il.findHandle(end_pc).getInstructionHandle(); + } + InstructionHandle instructionHandle2 = this.il.findHandle(codeException.getStart_pc()); + InstructionList instructionList = this.il; + int handler_pc = codeException.getHandler_pc(); + InstructionHandle instructionHandle3 = instructionHandle; + MethodGen methodGen2 = methodGen; + value8++; + methodGen2.addExceptionHandler( + instructionHandle2, + instructionHandle3, + instructionList.findHandle(handler_pc), + objectType); + } + } + Attribute[] attributes2 = code.getAttributes(); + int value10; + for (value2 = value10 = 0; value2 < attributes2.length; value2 = ++value10) { + Attribute attribute2; + if ((attribute2 = attributes2[value10]) instanceof LineNumberTable) { + LineNumber[] lineNumberTable = ((LineNumberTable) attribute2).getLineNumberTable(); + int value11; + for (int value12 = value11 = 0; value12 < lineNumberTable.length; value12 = ++value11) { + LineNumber lineNumber = lineNumberTable[value11]; + InstructionHandle instructionHandle4; + if ((instructionHandle4 = this.il.findHandle(lineNumber.getStart_pc())) != null) { + this.addLineNumber(instructionHandle4, lineNumber.getLine_number()); + } + } + } else if (attribute2 instanceof LocalVariableTable) { + LocalVariable[] localVariableTable = + ((LocalVariableTable) attribute2).getLocalVariableTable(); + value2 = 0; + this.getVariable_vec(); + for (int index = 0; value2 < localVariableTable.length; value2 = index) { + LocalVariable localVariable = localVariableTable[index]; + InstructionHandle instructionHandle5 = + this.il.findHandle(localVariable.getStart_pc()); + InstructionHandle instructionHandle6 = + this.il.findHandle(localVariable.getStart_pc() + localVariable.getLength()); + if (null == instructionHandle5) { + instructionHandle5 = this.il.getStart(); + } + if (null == instructionHandle6) { + instructionHandle6 = this.il.getEnd(); + } + String text3 = localVariable.getText(); + type = Type.getType(localVariable.getText2()); + int index2 = localVariable.getIndex(); + Type type2 = type; + index++; + this.addLocalVariable(text3, type2, index2, instructionHandle5, instructionHandle6); + } + } else { + this.addCodeAttribute(attribute2); + } + } + } + } + } + + public void removeExceptionHandler(CodeExceptionGen codeExceptionGen) { + this.exception_vec.remove(codeExceptionGen); + } + + public void processConstantPoolGen(ConstantPoolGen constantPoolGen) { + if (this.hasParameterAnnotations) { + int value; + Attribute[] attributes; + if ((attributes = Utility.createAttributes(constantPoolGen, this.param_annotations)) + != null) { + for (int value2 = value = 0; value2 < attributes.length; value2 = value) { + int value3 = value; + Attribute[] attributes2 = attributes; + value++; + this.addAttribute(attributes2[value3]); + } + } + } + } + + public int getCount2() { + return this.count2; + } + + public Type[] getArgumentTypes() { + return (Type[]) this.arg_types.clone(); + } + + public void update5() { + if (this.il != null) { + this.count2 = getMaxStack(this.cp, this.il, this.getExceptionHandlers()); + if (this.count2 == 0 && this.exception_vec != null && this.exception_vec.size() > 0) { + this.count2 = 1; + return; + } + } else { + this.count2 = 0; + } + } + + public static final void processCount( + LocalVariableGen[] localVariableGens, int value, int value2) { + int value3 = value; + int value4 = value2; + int index = localVariableGens[(value + value2) / 2].getIndex(); + do { + LocalVariableGen[] localVariableGens2 = localVariableGens; + while (localVariableGens2[value3].getIndex() < index) { + value3++; + localVariableGens2 = localVariableGens; + } + int value5 = index; + while (value5 < localVariableGens[value4].getIndex()) { + value4--; + value5 = index; + } + if (value3 <= value4) { + LocalVariableGen localVariableGen = localVariableGens[value3]; + localVariableGens[value3] = localVariableGens[value4]; + int value6 = value4; + value3++; + localVariableGens[value6] = localVariableGen; + value4--; + } + } while (value3 <= value4); + if (value < value4) { + processCount(localVariableGens, value, value4); + } + if (value3 < value2) { + processCount(localVariableGens, value3, value2); + } + } + + public Method getMethod() { + String text = this.getText(); + int value = this.cp.addUtf8(this.name); + int value2 = this.cp.addUtf8(text); + byte[] values = null; + if (this.il != null) { + values = this.il.getByteCode(); + } + LineNumberTable lineNumberTable = null; + LocalVariableTable localVariableTable = null; + if (this.variable_vec.size() > 0 && !this.strip_attributes) { + this.addCodeAttribute(localVariableTable = this.getLocalVariableTable(this.cp)); + } + if (this.line_number_vec.size() > 0 && !this.strip_attributes) { + this.addCodeAttribute(lineNumberTable = this.getLineNumberTable(this.cp)); + } + Attribute[] codeAttributes = this.getCodeAttributes(); + int value3 = 0; + int value4; + for (int value5 = value4 = 0; value5 < codeAttributes.length; value5 = value4) { + int length2 = codeAttributes[value4].getLength(); + int value6 = value3; + value4++; + value3 = value6 + length2 + (byte) 6; + } + CodeException[] codeExceptions; + int value7 = (codeExceptions = this.getCodeExceptions()).length * 8; + Code code = null; + if (this.il != null && !this.isEnabled15() && !this.isEnabled14()) { + Attribute[] attributes = this.getAttributes(); + int value8; + for (int value9 = value8 = 0; value9 < attributes.length; value9 = ++value8) { + Attribute attribute; + if ((attribute = attributes[value8]) instanceof Code) { + this.removeAttribute(attribute); + } + } + code = + new Code( + this.cp.addUtf8("Code"), + 8 + values.length + 2 + value7 + 2 + value3, + this.count2, + this.count, + values, + codeExceptions, + codeAttributes, + this.cp.getConstantPool()); + this.addAttribute(code); + } + this.processConstantPoolGen2(this.cp); + this.processConstantPoolGen(this.cp); + ExceptionTable exceptionTable = null; + if (this.throws_vec.size() > 0) { + this.addAttribute(exceptionTable = this.getExceptionTable(this.cp)); + } + Method method = + new Method( + this.access_flags, value, value2, this.getAttributes(), this.cp.getConstantPool()); + if (localVariableTable != null) { + this.removeCodeAttribute(localVariableTable); + } + if (lineNumberTable != null) { + this.removeCodeAttribute(lineNumberTable); + } + if (code != null) { + this.removeAttribute(code); + } + if (exceptionTable != null) { + this.removeAttribute(exceptionTable); + } + return method; + } + + public void setReturnType(Type type) { + this.setType(type); + } + + public LocalVariableGen[] getLocalVariables() { + int value; + LocalVariableGen[] localVariableGens = new LocalVariableGen[value = this.variable_vec.size()]; + this.variable_vec.toArray(localVariableGens); + int value2 = 0; + for (int value3 = value2; value3 < value; value3 = ++value2) { + if (localVariableGens[value2].getInstructionHandle() == null) { + localVariableGens[value2].processInstructionHandle2(this.il.getStart()); + } + if (localVariableGens[value2].getInstructionHandle2() == null) { + localVariableGens[value2].processInstructionHandle(this.il.getEnd()); + } + } + if (value > 1) { + processCount(localVariableGens, 0, value - 1); + } + return localVariableGens; + } + + public LineNumberGen[] getLineNumbers() { + LineNumberGen[] lineNumberGens = new LineNumberGen[this.line_number_vec.size()]; + this.line_number_vec.toArray(lineNumberGens); + return lineNumberGens; + } + + public List makeMutableVersion(AnnotationEntry[] annotationEntrys) { + ArrayList values = new ArrayList(); + int value; + for (int value2 = value = 0; value2 < annotationEntrys.length; value2 = value) { + AnnotationEntry annotationEntry = annotationEntrys[value]; + ConstantPoolGen constantPool = this.getConstantPool(); + value++; + values.add(new AnnotationEntryGen(annotationEntry, constantPool, false)); + } + return values; + } + + public void setCount2(int count2) { + this.count2 = count2; + } + + public void processConstantPoolGen2(ConstantPoolGen constantPoolGen) { + int value; + Attribute[] attributes; + if ((attributes = Utility.createAttributes(constantPoolGen, this.arrayList)) != null) { + for (int value2 = value = 0; value2 < attributes.length; value2 = value) { + int value3 = value; + Attribute[] attributes2 = attributes; + value++; + this.addAttribute(attributes2[value3]); + } + } + } + + public void removeException(String text) { + this.throws_vec.remove(text); + } + + @Override + public boolean equals(Object result) { + return bcelComparator.equals(this, result); + } + + public void removeLineNumber(LineNumberGen lineNumberGen) { + this.line_number_vec.remove(lineNumberGen); + } + + public void processMethodObserver2(MethodObserver methodObserver) { + if (this.values != null) { + this.values.remove(methodObserver); + } + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/MethodObserver.java b/src/main/java/com/allatori/lib/bcel/generic/MethodObserver.java new file mode 100644 index 0000000..9583140 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/MethodObserver.java @@ -0,0 +1,6 @@ +package com.allatori.lib.bcel.generic; + +public interface MethodObserver { + + void notify(MethodGen methodGen); +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/NEW.java b/src/main/java/com/allatori/lib/bcel/generic/NEW.java new file mode 100644 index 0000000..8bdad80 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/NEW.java @@ -0,0 +1,38 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.ExceptionConstants; + +public class NEW extends CPInstruction + implements LoadClass, AllocationInstruction, ExceptionThrower, StackProducer { + + @Override + public void accept(Visitor visitor) { + visitor.visitLoadClass(this); + visitor.visitAllocationInstruction(this); + visitor.visitExceptionThrower(this); + visitor.visitStackProducer(this); + visitor.visitTypedInstruction(this); + visitor.visitCPInstruction(this); + visitor.visitNEW(this); + } + + @Override + public Class[] getExceptions() { + Class[] classs = new Class[2 + ExceptionConstants.TYPES5.length]; + System.arraycopy(ExceptionConstants.TYPES5, 0, classs, 0, ExceptionConstants.TYPES5.length); + classs[ExceptionConstants.TYPES5.length + 1] = ExceptionConstants.TYPE2; + classs[ExceptionConstants.TYPES5.length] = ExceptionConstants.TYPE7; + return classs; + } + + public NEW(int value) { + super((short) 187, value); + } + + @Override + public ObjectType getLoadClassType(ConstantPoolGen constantPoolGen) { + return (ObjectType) this.getType(constantPoolGen); + } + + public NEW() {} +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/NEWARRAY.java b/src/main/java/com/allatori/lib/bcel/generic/NEWARRAY.java new file mode 100644 index 0000000..f9ff994 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/NEWARRAY.java @@ -0,0 +1,62 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.Constants; +import com.allatori.lib.bcel.ExceptionConstants; +import com.allatori.lib.bcel.util.ByteSequence; +import java.io.DataOutputStream; +import java.io.IOException; + +public class NEWARRAY extends Instruction + implements AllocationInstruction, ExceptionThrower, StackProducer { + + public byte type; + + public NEWARRAY(BasicType basicType) { + this(basicType.getType()); + } + + public NEWARRAY(byte type) { + super((short) 188, (short) 2); + this.type = type; + } + + @Override + public Class[] getExceptions() { + return new Class[] {ExceptionConstants.TYPE11}; + } + + @Override + public String toString(boolean matches) { + return "" + super.toString(matches) + " " + Constants.TEXTS[this.type]; + } + + @Override + public void accept(Visitor visitor) { + visitor.visitAllocationInstruction(this); + visitor.visitExceptionThrower(this); + visitor.visitStackProducer(this); + visitor.visitNEWARRAY(this); + } + + public final byte getTypecode() { + return this.type; + } + + public final Type getType() { + return new ArrayType(BasicType.getType(this.type), 1); + } + + public NEWARRAY() {} + + @Override + public void dump(DataOutputStream dataOutputStream) throws IOException { + dataOutputStream.writeByte(this.opcode); + dataOutputStream.writeByte(this.type); + } + + @Override + public void initFromFile(ByteSequence byteSequence, boolean matches) throws IOException { + this.type = byteSequence.readByte(); + this.length = 2; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/NOP.java b/src/main/java/com/allatori/lib/bcel/generic/NOP.java new file mode 100644 index 0000000..29e6a98 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/NOP.java @@ -0,0 +1,13 @@ +package com.allatori.lib.bcel.generic; + +public class NOP extends Instruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitNOP(this); + } + + public NOP() { + super((short) 0, (short) 1); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/NameSignatureInstruction.java b/src/main/java/com/allatori/lib/bcel/generic/NameSignatureInstruction.java new file mode 100644 index 0000000..5f36deb --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/NameSignatureInstruction.java @@ -0,0 +1,34 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.classfile.ConstantCP; +import com.allatori.lib.bcel.classfile.ConstantNameAndType; +import com.allatori.lib.bcel.classfile.ConstantPool; +import com.allatori.lib.bcel.classfile.ConstantUtf8; + +public abstract class NameSignatureInstruction extends CPInstruction { + + public NameSignatureInstruction(short value, int value2) { + super(value, value2); + } + + public NameSignatureInstruction() {} + + public String getText(ConstantPoolGen constantPoolGen) { + ConstantPool constantPool = constantPoolGen.getConstantPool(); + ConstantNameAndType nameAndType = this.getNameAndType(constantPoolGen); + return ((ConstantUtf8) constantPool.getConstant(nameAndType.getSignature_index())).getBytes(); + } + + public String getText2(ConstantPoolGen constantPoolGen) { + ConstantPool constantPool = constantPoolGen.getConstantPool(); + ConstantNameAndType nameAndType = this.getNameAndType(constantPoolGen); + return ((ConstantUtf8) constantPool.getConstant(nameAndType.getName_index())).getBytes(); + } + + public ConstantNameAndType getNameAndType(ConstantPoolGen constantPoolGen) { + ConstantPool constantPool; + ConstantCP constantCP = + (ConstantCP) (constantPool = constantPoolGen.getConstantPool()).getConstant(this.index); + return (ConstantNameAndType) constantPool.getConstant(constantCP.getName_and_type_index()); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/NamedAndTyped.java b/src/main/java/com/allatori/lib/bcel/generic/NamedAndTyped.java new file mode 100644 index 0000000..b908081 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/NamedAndTyped.java @@ -0,0 +1,12 @@ +package com.allatori.lib.bcel.generic; + +public interface NamedAndTyped { + + void setName(String text); + + void setType(Type type); + + String getName(); + + Type getType(); +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/ObjectType.java b/src/main/java/com/allatori/lib/bcel/generic/ObjectType.java new file mode 100644 index 0000000..8abb8e3 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/ObjectType.java @@ -0,0 +1,73 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.Repository; +import com.allatori.lib.bcel.classfile.JavaClass; + +public class ObjectType extends ReferenceType { + + public String class_name; + + @Override + public boolean equals(Object result) { + return result instanceof ObjectType + ? ((ObjectType) result).class_name.equals(this.class_name) + : false; + } + + public boolean matchesObjectType(ObjectType objectType) throws ClassNotFoundException { + return !this.isEnabled2() && !objectType.isEnabled2() + ? Repository.matchesText(this.class_name, objectType.class_name) + : false; + } + + public ObjectType(String text) { + super((byte) 14, ("L" + text.replace('.', '/') + ";")); + this.class_name = text.replace('/', '.'); + } + + @Override + public int hashCode() { + return this.class_name.hashCode(); + } + + public boolean isEnabled() throws ClassNotFoundException { + return !Repository.lookupClass(this.class_name).isEnabled17(); + } + + public String getClassName() { + return this.class_name; + } + + /** + * @deprecated + */ + public boolean isEnabled2() { + try { + return !Repository.lookupClass(this.class_name).isEnabled17(); + } catch (ClassNotFoundException classNotFoundException) { + return false; + } + } + + public boolean isClass_name() throws ClassNotFoundException { + return Repository.lookupClass(this.class_name).isEnabled17(); + } + + /** + * @deprecated + */ + public boolean isClass_name2() { + try { + return Repository.lookupClass(this.class_name).isEnabled17(); + } catch (ClassNotFoundException classNotFoundException) { + return false; + } + } + + public boolean matchesObjectType2(ObjectType objectType) throws ClassNotFoundException { + JavaClass javaClass; + return (javaClass = Repository.lookupClass(this.class_name)).isEnabled6() + ? true + : Repository.lookupClass(objectType.class_name).getText4().equals(javaClass.getText4()); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/POP.java b/src/main/java/com/allatori/lib/bcel/generic/POP.java new file mode 100644 index 0000000..d6ca1bf --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/POP.java @@ -0,0 +1,16 @@ +package com.allatori.lib.bcel.generic; + +public class POP extends StackInstruction implements PopInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitStackConsumer(this); + visitor.visitPopInstruction(this); + visitor.visitStackInstruction(this); + visitor.visitPOP(this); + } + + public POP() { + super((short) 87); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/POP2.java b/src/main/java/com/allatori/lib/bcel/generic/POP2.java new file mode 100644 index 0000000..5689fc5 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/POP2.java @@ -0,0 +1,16 @@ +package com.allatori.lib.bcel.generic; + +public class POP2 extends StackInstruction implements PopInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitStackConsumer(this); + visitor.visitPopInstruction(this); + visitor.visitStackInstruction(this); + visitor.visitPOP2(this); + } + + public POP2() { + super((short) 88); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/PUSH.java b/src/main/java/com/allatori/lib/bcel/generic/PUSH.java new file mode 100644 index 0000000..0b5e5b5 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/PUSH.java @@ -0,0 +1,101 @@ +package com.allatori.lib.bcel.generic; + +public final class PUSH + implements CompoundInstruction, VariableLengthInstruction, InstructionConstants { + + public Instruction instruction; + + public PUSH(ConstantPoolGen constantPoolGen, String text) { + super(); + if (text == null) { + this.instruction = ACONST_NULL; + } else { + this.instruction = new LDC(constantPoolGen.addString(text)); + } + } + + public PUSH(ConstantPoolGen constantPoolGen, Number number) { + super(); + if (number instanceof Integer || number instanceof Short || number instanceof Byte) { + this.instruction = new PUSH(constantPoolGen, number.intValue()).instruction; + } else if (number instanceof Double) { + this.instruction = new PUSH(constantPoolGen, number.doubleValue()).instruction; + } else if (number instanceof Float) { + this.instruction = new PUSH(constantPoolGen, number.floatValue()).instruction; + } else if (number instanceof Long) { + this.instruction = new PUSH(constantPoolGen, number.longValue()).instruction; + } else { + throw new ClassGenException(("What's this: " + number)); + } + } + + public PUSH(ConstantPoolGen constantPoolGen, boolean matches) { + super(); + this.instruction = INSTRUCTIONS[3 + (matches ? 1 : 0)]; + } + + public PUSH(ConstantPoolGen constantPoolGen, float value) { + super(); + if (value == 0.0) { + this.instruction = FCONST_0; + } else if (value == 1.0) { + this.instruction = FCONST_1; + } else if (value == 2.0) { + this.instruction = FCONST_2; + } else { + this.instruction = new LDC(constantPoolGen.addFloat(value)); + } + } + + public PUSH(ConstantPoolGen constantPoolGen, int value) { + super(); + if (value >= -1 && value <= 5) { + this.instruction = INSTRUCTIONS[3 + value]; + } else if (value >= -128 && value <= 127) { + this.instruction = new BIPUSH((byte) value); + } else if (value >= -32768 && value <= 32767) { + this.instruction = new SIPUSH((short) value); + } else { + this.instruction = new LDC(constantPoolGen.addInteger(value)); + } + } + + @Override + public final InstructionList getInstructionList() { + return new InstructionList(this.instruction); + } + + public final Instruction getInstruction() { + return this.instruction; + } + + public PUSH(ConstantPoolGen constantPoolGen, long value) { + super(); + if (value == 0L) { + this.instruction = LCONST_0; + } else if (value == 1L) { + this.instruction = LCONST_1; + } else { + this.instruction = new LDC2_W(constantPoolGen.addLong(value)); + } + } + + public PUSH(ConstantPoolGen constantPoolGen, Character character) { + this(constantPoolGen, character.charValue()); + } + + public PUSH(ConstantPoolGen constantPoolGen, Boolean matches) { + this(constantPoolGen, matches.booleanValue()); + } + + public PUSH(ConstantPoolGen constantPoolGen, double value) { + super(); + if (value == 0.0) { + this.instruction = DCONST_0; + } else if (value == 1.0) { + this.instruction = DCONST_1; + } else { + this.instruction = new LDC2_W(constantPoolGen.addDouble(value)); + } + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/PUTFIELD.java b/src/main/java/com/allatori/lib/bcel/generic/PUTFIELD.java new file mode 100644 index 0000000..40bba3f --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/PUTFIELD.java @@ -0,0 +1,39 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.ExceptionConstants; + +public class PUTFIELD extends FieldInstruction implements PopInstruction, ExceptionThrower { + + public PUTFIELD() {} + + @Override + public int consumeStack(ConstantPoolGen constantPoolGen) { + return this.getFieldSize(constantPoolGen) + 1; + } + + public PUTFIELD(int value) { + super((short) 181, value); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitExceptionThrower(this); + visitor.visitStackConsumer(this); + visitor.visitPopInstruction(this); + visitor.visitTypedInstruction(this); + visitor.visitLoadClass(this); + visitor.visitCPInstruction(this); + visitor.visitFieldOrMethod(this); + visitor.visitFieldInstruction(this); + visitor.visitPUTFIELD(this); + } + + @Override + public Class[] getExceptions() { + Class[] classs = new Class[2 + ExceptionConstants.TYPES2.length]; + System.arraycopy(ExceptionConstants.TYPES2, 0, classs, 0, ExceptionConstants.TYPES2.length); + classs[ExceptionConstants.TYPES2.length + 1] = ExceptionConstants.TYPE9; + classs[ExceptionConstants.TYPES2.length] = ExceptionConstants.TYPE3; + return classs; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/PUTSTATIC.java b/src/main/java/com/allatori/lib/bcel/generic/PUTSTATIC.java new file mode 100644 index 0000000..a53c048 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/PUTSTATIC.java @@ -0,0 +1,38 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.ExceptionConstants; + +public class PUTSTATIC extends FieldInstruction implements ExceptionThrower, PopInstruction { + + @Override + public void accept(Visitor visitor) { + visitor.visitExceptionThrower(this); + visitor.visitStackConsumer(this); + visitor.visitPopInstruction(this); + visitor.visitTypedInstruction(this); + visitor.visitLoadClass(this); + visitor.visitCPInstruction(this); + visitor.visitFieldOrMethod(this); + visitor.visitFieldInstruction(this); + visitor.visitPUTSTATIC(this); + } + + @Override + public int consumeStack(ConstantPoolGen constantPoolGen) { + return this.getFieldSize(constantPoolGen); + } + + public PUTSTATIC() {} + + public PUTSTATIC(int value) { + super((short) 179, value); + } + + @Override + public Class[] getExceptions() { + Class[] classs = new Class[1 + ExceptionConstants.TYPES2.length]; + System.arraycopy(ExceptionConstants.TYPES2, 0, classs, 0, ExceptionConstants.TYPES2.length); + classs[ExceptionConstants.TYPES2.length] = ExceptionConstants.TYPE9; + return classs; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/PopInstruction.java b/src/main/java/com/allatori/lib/bcel/generic/PopInstruction.java new file mode 100644 index 0000000..4cb9967 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/PopInstruction.java @@ -0,0 +1,3 @@ +package com.allatori.lib.bcel.generic; + +public interface PopInstruction extends StackConsumer {} diff --git a/src/main/java/com/allatori/lib/bcel/generic/PushInstruction.java b/src/main/java/com/allatori/lib/bcel/generic/PushInstruction.java new file mode 100644 index 0000000..a10ec4a --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/PushInstruction.java @@ -0,0 +1,3 @@ +package com.allatori.lib.bcel.generic; + +public interface PushInstruction extends StackProducer {} diff --git a/src/main/java/com/allatori/lib/bcel/generic/RET.java b/src/main/java/com/allatori/lib/bcel/generic/RET.java new file mode 100644 index 0000000..888268d --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/RET.java @@ -0,0 +1,81 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.util.ByteSequence; +import java.io.DataOutputStream; +import java.io.IOException; + +public class RET extends Instruction implements IndexedInstruction, TypedInstruction { + + public int index; + + public boolean wide; + + @Override + public final int getIndex() { + return this.index; + } + + @Override + public void accept(Visitor visitor) { + visitor.visitRET(this); + } + + public RET() {} + + public final void setWide() { + this.wide = this.index > 255; + if (this.wide) { + this.length = 4; + } else { + this.length = 2; + } + } + + @Override + public Type getType(ConstantPoolGen constantPoolGen) { + return ReturnaddressType.NO_TARGET; + } + + @Override + public void initFromFile(ByteSequence byteSequence, boolean wide) throws IOException { + if (this.wide = wide) { + this.index = byteSequence.readUnsignedShort(); + this.length = 4; + } else { + this.index = byteSequence.readUnsignedByte(); + this.length = 2; + } + } + + @Override + public String toString(boolean matches) { + return "" + super.toString(matches) + " " + this.index; + } + + @Override + public final void setIndex(int index) { + if (index < 0) { + throw new ClassGenException(("Negative index value: " + index)); + } + this.index = index; + this.setWide(); + } + + @Override + public void dump(DataOutputStream dataOutputStream) throws IOException { + if (this.wide) { + dataOutputStream.writeByte(196); + } + dataOutputStream.writeByte(this.opcode); + if (this.wide) { + dataOutputStream.writeShort(this.index); + } else { + dataOutputStream.writeByte(this.index); + } + } + + public RET(int value) { + super((short) 169, (short) 2); + this.setIndex(value); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/RETURN.java b/src/main/java/com/allatori/lib/bcel/generic/RETURN.java new file mode 100644 index 0000000..99a110b --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/RETURN.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class RETURN extends ReturnInstruction { + + public RETURN() { + super((short) 177); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitExceptionThrower(this); + visitor.visitTypedInstruction(this); + visitor.visitStackConsumer(this); + visitor.visitReturnInstruction(this); + visitor.visitRETURN(this); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/ReferenceType.java b/src/main/java/com/allatori/lib/bcel/generic/ReferenceType.java new file mode 100644 index 0000000..496f8eb --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/ReferenceType.java @@ -0,0 +1,199 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.Constants; +import com.allatori.lib.bcel.Repository; +import com.allatori.lib.bcel.classfile.JavaClass; + +public abstract class ReferenceType extends Type { + + public ReferenceType() { + super((byte) 14, ""); + } + + public boolean matchesType(Type type) throws ClassNotFoundException { + return this.equals(Type.NULL) ? true : this.matchesType2(type); + } + + public ReferenceType createReferenceType(ReferenceType referenceType) + throws ClassNotFoundException { + if (this.equals(Type.NULL)) { + return referenceType; + } + if (referenceType.equals(Type.NULL)) { + return this; + } + if (this.equals(referenceType)) { + return this; + } + if (this instanceof ArrayType && referenceType instanceof ArrayType) { + ArrayType arrayType = (ArrayType) referenceType; + if (((ArrayType) this).getDimensions() == arrayType.getDimensions() + && ((ArrayType) this).getBasicType() instanceof ObjectType + && arrayType.getBasicType() instanceof ObjectType) { + return new ArrayType( + ((ObjectType) ((ArrayType) this).getBasicType()) + .createReferenceType((ObjectType) arrayType.getBasicType()), + ((ArrayType) this).getDimensions()); + } + } + if (!(this instanceof ArrayType) && !(referenceType instanceof ArrayType)) { + if ((!(this instanceof ObjectType) || !((ObjectType) this).isEnabled2()) + && (!(referenceType instanceof ObjectType) + || !((ObjectType) referenceType).isEnabled2())) { + ObjectType objectType = (ObjectType) referenceType; + JavaClass[] javaClasss = Repository.getJavaClasss(((ObjectType) this).getClassName()); + JavaClass[] javaClasss2 = Repository.getJavaClasss(objectType.getClassName()); + if (javaClasss != null && javaClasss2 != null) { + JavaClass[] javaClasss3 = new JavaClass[javaClasss.length + 1]; + JavaClass[] javaClasss4 = new JavaClass[javaClasss2.length + 1]; + System.arraycopy(javaClasss, 0, javaClasss3, 1, javaClasss.length); + System.arraycopy(javaClasss2, 0, javaClasss4, 1, javaClasss2.length); + int value = 0; + javaClasss3[0] = Repository.lookupClass(((ObjectType) this).getClassName()); + javaClasss4[0] = Repository.lookupClass(objectType.getClassName()); + int value2; + for (int index = 0; value < javaClasss4.length; value = ++index) { + for (int value3 = value2 = 0; value3 < javaClasss3.length; value3 = ++value2) { + if (javaClasss3[value2].equals(javaClasss4[index])) { + return new ObjectType(javaClasss3[value2].getText2()); + } + } + } + return null; + } else { + return null; + } + } else { + return Type.OBJECT; + } + } else { + return Type.OBJECT; + } + } + + public boolean matchesType2(Type type) throws ClassNotFoundException { + if (!(type instanceof ReferenceType)) { + return false; + } + ReferenceType referenceType = (ReferenceType) type; + if (this.equals(Type.NULL)) { + return true; + } + if (this instanceof ObjectType && ((ObjectType) this).isClass_name()) { + if (referenceType instanceof ObjectType && ((ObjectType) referenceType).isClass_name()) { + if (this.equals(referenceType)) { + return true; + } + if (Repository.matchesText( + ((ObjectType) this).getClassName(), ((ObjectType) referenceType).getClassName())) { + return true; + } + } + if (referenceType instanceof ObjectType + && ((ObjectType) referenceType).isEnabled() + && Repository.matchesText2( + ((ObjectType) this).getClassName(), ((ObjectType) referenceType).getClassName())) { + return true; + } + } + if (this instanceof ObjectType && ((ObjectType) this).isEnabled()) { + if (referenceType instanceof ObjectType + && ((ObjectType) referenceType).isClass_name() + && referenceType.equals(Type.OBJECT)) { + return true; + } + if (referenceType instanceof ObjectType && ((ObjectType) referenceType).isEnabled()) { + if (this.equals(referenceType)) { + return true; + } + if (Repository.matchesText2( + ((ObjectType) this).getClassName(), ((ObjectType) referenceType).getClassName())) { + return true; + } + } + } + if (this instanceof ArrayType) { + if (referenceType instanceof ObjectType + && ((ObjectType) referenceType).isClass_name() + && referenceType.equals(Type.OBJECT)) { + return true; + } + if (referenceType instanceof ArrayType) { + Type elementType = ((ArrayType) this).getElementType(); + Type elementType2 = ((ArrayType) referenceType).getElementType(); + if (elementType instanceof BasicType + && elementType2 instanceof BasicType + && elementType.equals(elementType2)) { + return true; + } + if (elementType2 instanceof ReferenceType + && elementType instanceof ReferenceType + && ((ReferenceType) elementType).matchesType2(elementType2)) { + return true; + } + } + int value; + if (referenceType instanceof ObjectType && ((ObjectType) referenceType).isEnabled()) { + for (int value2 = value = 0; value2 < Constants.TEXTS5.length; value2 = ++value) { + if (referenceType.equals(new ObjectType(Constants.TEXTS5[value]))) { + return true; + } + } + } + } + return false; + } + + public ReferenceType(byte value, String text) { + super(value, text); + } + + /** + * @deprecated + */ + public ReferenceType createReferenceType2(ReferenceType referenceType) + throws ClassNotFoundException { + if (this.equals(Type.NULL)) { + return referenceType; + } + if (referenceType.equals(Type.NULL)) { + return this; + } + if (this.equals(referenceType)) { + return this; + } + if (!(this instanceof ArrayType) && !(referenceType instanceof ArrayType)) { + if ((!(this instanceof ObjectType) || !((ObjectType) this).isEnabled2()) + && (!(referenceType instanceof ObjectType) + || !((ObjectType) referenceType).isEnabled2())) { + ObjectType objectType = (ObjectType) referenceType; + JavaClass[] javaClasss = Repository.getJavaClasss(((ObjectType) this).getClassName()); + JavaClass[] javaClasss2 = Repository.getJavaClasss(objectType.getClassName()); + if (javaClasss != null && javaClasss2 != null) { + JavaClass[] javaClasss3 = new JavaClass[javaClasss.length + 1]; + JavaClass[] javaClasss4 = new JavaClass[javaClasss2.length + 1]; + System.arraycopy(javaClasss, 0, javaClasss3, 1, javaClasss.length); + System.arraycopy(javaClasss2, 0, javaClasss4, 1, javaClasss2.length); + int value = 0; + javaClasss3[0] = Repository.lookupClass(((ObjectType) this).getClassName()); + javaClasss4[0] = Repository.lookupClass(objectType.getClassName()); + int value2; + for (int index = 0; value < javaClasss4.length; value = ++index) { + for (int value3 = value2 = 0; value3 < javaClasss3.length; value3 = ++value2) { + if (javaClasss3[value2].equals(javaClasss4[index])) { + return new ObjectType(javaClasss3[value2].getText2()); + } + } + } + return null; + } else { + return null; + } + } else { + return Type.OBJECT; + } + } else { + return Type.OBJECT; + } + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/ReturnInstruction.java b/src/main/java/com/allatori/lib/bcel/generic/ReturnInstruction.java new file mode 100644 index 0000000..77fcda8 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/ReturnInstruction.java @@ -0,0 +1,42 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.ExceptionConstants; + +public abstract class ReturnInstruction extends Instruction + implements ExceptionThrower, TypedInstruction, StackConsumer { + + public Type getType() { + switch (this.opcode) { + case 172: + return Type.INT; + case 173: + return Type.LONG; + case 174: + return Type.FLOAT; + case 175: + return Type.DOUBLE; + case 176: + return Type.OBJECT; + case 177: + return Type.VOID; + default: + throw new ClassGenException(("Unknown type " + this.opcode)); + } + } + + @Override + public Class[] getExceptions() { + return new Class[] {ExceptionConstants.TYPE19}; + } + + public ReturnInstruction() {} + + @Override + public Type getType(ConstantPoolGen constantPoolGen) { + return this.getType(); + } + + public ReturnInstruction(short value) { + super(value, (short) 1); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/ReturnaddressType.java b/src/main/java/com/allatori/lib/bcel/generic/ReturnaddressType.java new file mode 100644 index 0000000..79942f1 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/ReturnaddressType.java @@ -0,0 +1,37 @@ +package com.allatori.lib.bcel.generic; + +public class ReturnaddressType extends Type { + + public static final ReturnaddressType NO_TARGET = new ReturnaddressType(); + + public InstructionHandle returnTarget; + + @Override + public int hashCode() { + return this.returnTarget == null ? 0 : this.returnTarget.hashCode(); + } + + public ReturnaddressType(InstructionHandle instructionHandle) { + super((byte) 16, ("")); + this.returnTarget = instructionHandle; + } + + public InstructionHandle getTarget() { + return this.returnTarget; + } + + public ReturnaddressType() { + super((byte) 16, ""); + } + + @Override + public boolean equals(Object result) { + if (!(result instanceof ReturnaddressType)) { + return false; + } + ReturnaddressType returnaddressType = (ReturnaddressType) result; + return this.returnTarget != null && returnaddressType.returnTarget != null + ? returnaddressType.returnTarget.equals(this.returnTarget) + : returnaddressType.returnTarget == this.returnTarget; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/SALOAD.java b/src/main/java/com/allatori/lib/bcel/generic/SALOAD.java new file mode 100644 index 0000000..4dcfde1 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/SALOAD.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class SALOAD extends ArrayInstruction implements StackProducer { + + public SALOAD() { + super((short) 53); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitStackProducer(this); + visitor.visitExceptionThrower(this); + visitor.visitTypedInstruction(this); + visitor.visitArrayInstruction(this); + visitor.visitSALOAD(this); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/SASTORE.java b/src/main/java/com/allatori/lib/bcel/generic/SASTORE.java new file mode 100644 index 0000000..e563e74 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/SASTORE.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.generic; + +public class SASTORE extends ArrayInstruction implements StackConsumer { + + @Override + public void accept(Visitor visitor) { + visitor.visitStackConsumer(this); + visitor.visitExceptionThrower(this); + visitor.visitTypedInstruction(this); + visitor.visitArrayInstruction(this); + visitor.visitSASTORE(this); + } + + public SASTORE() { + super((short) 86); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/SIPUSH.java b/src/main/java/com/allatori/lib/bcel/generic/SIPUSH.java new file mode 100644 index 0000000..13b3653 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/SIPUSH.java @@ -0,0 +1,53 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.util.ByteSequence; +import java.io.DataOutputStream; +import java.io.IOException; + +public class SIPUSH extends Instruction implements ConstantPushInstruction { + + public short b; + + @Override + public String toString(boolean matches) { + return "" + super.toString(matches) + " " + this.b; + } + + @Override + public void accept(Visitor visitor) { + visitor.visitPushInstruction(this); + visitor.visitStackProducer(this); + visitor.visitTypedInstruction(this); + visitor.visitConstantPushInstruction(this); + visitor.visitSIPUSH(this); + } + + public SIPUSH(short b) { + super((short) 17, (short) 3); + this.b = b; + } + + public SIPUSH() {} + + @Override + public Number getValue() { + return new Integer(this.b); + } + + @Override + public void dump(DataOutputStream dataOutputStream) throws IOException { + super.dump(dataOutputStream); + dataOutputStream.writeShort(this.b); + } + + @Override + public void initFromFile(ByteSequence byteSequence, boolean matches) throws IOException { + this.length = 3; + this.b = byteSequence.readShort(); + } + + @Override + public Type getType(ConstantPoolGen constantPoolGen) { + return Type.SHORT; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/SWAP.java b/src/main/java/com/allatori/lib/bcel/generic/SWAP.java new file mode 100644 index 0000000..8e497d7 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/SWAP.java @@ -0,0 +1,16 @@ +package com.allatori.lib.bcel.generic; + +public class SWAP extends StackInstruction implements StackConsumer, StackProducer { + + public SWAP() { + super((short) 95); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitStackConsumer(this); + visitor.visitStackProducer(this); + visitor.visitStackInstruction(this); + visitor.visitSWAP(this); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/SWITCH.java b/src/main/java/com/allatori/lib/bcel/generic/SWITCH.java new file mode 100644 index 0000000..a10fce9 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/SWITCH.java @@ -0,0 +1,123 @@ +package com.allatori.lib.bcel.generic; + +public final class SWITCH implements CompoundInstruction { + + public InstructionHandle[] targets; + + public int[] match; + + public Select instruction; + + public int match_length; + + @Override + public final InstructionList getInstructionList() { + return new InstructionList(this.instruction); + } + + public SWITCH( + int[] values, + InstructionHandle[] instructionHandles, + InstructionHandle instructionHandle, + int value) { + super(); + this.match = (int[]) values.clone(); + this.targets = (InstructionHandle[]) instructionHandles.clone(); + if ((this.match_length = values.length) < 2) { + this.instruction = new TABLESWITCH(values, instructionHandles, instructionHandle); + } else { + this.sort(0, this.match_length - 1); + if (this.matchIsOrdered(value)) { + this.fillup(value, instructionHandle); + this.instruction = new TABLESWITCH(this.match, this.targets, instructionHandle); + } else { + this.instruction = new LOOKUPSWITCH(this.match, this.targets, instructionHandle); + } + } + } + + public final boolean matchIsOrdered(int value) { + int value2; + for (int value3 = value2 = 1; value3 < this.match_length; value3 = ++value2) { + if (this.match[value2] - this.match[value2 - 1] > value) { + return false; + } + } + return true; + } + + public final void sort(int value, int value2) { + int value3 = value; + int value4 = value2; + int value5 = this.match[(value + value2) / 2]; + do { + SWITCH sWITCH = this; + while (sWITCH.match[value3] < value5) { + value3++; + sWITCH = this; + } + int value6 = value5; + while (value6 < this.match[value4]) { + value4--; + value6 = value5; + } + if (value3 <= value4) { + int value7 = this.match[value3]; + this.match[value3] = this.match[value4]; + this.match[value4] = value7; + InstructionHandle instructionHandle = this.targets[value3]; + this.targets[value3] = this.targets[value4]; + int value8 = value4; + InstructionHandle[] instructionHandles = this.targets; + value3++; + instructionHandles[value8] = instructionHandle; + value4--; + } + } while (value3 <= value4); + if (value < value4) { + this.sort(value, value4); + } + if (value3 < value2) { + this.sort(value3, value2); + } + } + + public final void fillup(int value, InstructionHandle instructionHandle) { + int value2; + int[] values = new int[value2 = this.match_length + this.match_length * value]; + InstructionHandle[] instructionHandles = new InstructionHandle[value2]; + int value3 = 1; + int value4 = 1; + values[0] = this.match[0]; + instructionHandles[0] = this.targets[0]; + for (int index = 1; value4 < this.match_length; value4 = ++index) { + int value5 = this.match[index - 1]; + int value6 = this.match[index] - value5; + int value7; + for (int value8 = value7 = 1; value8 < value6; value8 = ++value7) { + values[value3] = value5 + value7; + int value9 = value3; + value3++; + instructionHandles[value9] = instructionHandle; + } + values[value3] = this.match[index]; + InstructionHandle instructionHandle2 = this.targets[index]; + int value10 = value3; + value3++; + instructionHandles[value10] = instructionHandle2; + } + this.match = new int[value3]; + this.targets = new InstructionHandle[value3]; + System.arraycopy(values, 0, this.match, 0, value3); + System.arraycopy(instructionHandles, 0, this.targets, 0, value3); + } + + public final Instruction getInstruction() { + return this.instruction; + } + + public SWITCH( + int[] values, InstructionHandle[] instructionHandles, InstructionHandle instructionHandle) { + this(values, instructionHandles, instructionHandle, 1); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/Select.java b/src/main/java/com/allatori/lib/bcel/generic/Select.java new file mode 100644 index 0000000..1a67532 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/Select.java @@ -0,0 +1,174 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.util.ByteSequence; +import java.io.DataOutputStream; +import java.io.IOException; + +public abstract class Select extends BranchInstruction + implements VariableLengthInstruction, StackProducer { + + public int[] match; + + public int match_length; + + public int fixed_length; + + public int[] indices; + + public int padding = 0; + + public InstructionHandle[] targets; + + public int[] getIndices() { + return this.indices; + } + + public InstructionHandle[] getTargets() { + return this.targets; + } + + public void setTarget(int value, InstructionHandle instructionHandle) { + notifyTarget(this.targets[value], instructionHandle, this); + this.targets[value] = instructionHandle; + } + + @Override + public String toString(boolean matches) { + StringBuffer stringBuffer = new StringBuffer(super.toString(matches)); + int value; + if (matches) { + for (int value2 = value = 0; value2 < this.match_length; value2 = value) { + String text = "null"; + if (this.targets[value] != null) { + text = this.targets[value].getInstruction().toString(); + } + StringBuffer stringBuffer2 = + stringBuffer + .append("(") + .append(this.match[value]) + .append(", ") + .append(text) + .append(" = {") + .append(this.indices[value]); + value++; + stringBuffer2.append("})"); + } + } else { + stringBuffer.append(" ..."); + } + return stringBuffer.toString(); + } + + @Override + public void dump(DataOutputStream dataOutputStream) throws IOException { + int value = 0; + dataOutputStream.writeByte(this.opcode); + for (int index2 = 0; value < this.padding; value = index2) { + index2++; + dataOutputStream.writeByte(0); + } + this.index = this.getTargetOffset(); + dataOutputStream.writeInt(this.index); + } + + @Override + public void initFromFile(ByteSequence byteSequence, boolean matches) throws IOException { + int value = 0; + this.padding = (4 - byteSequence.getIndex() % 4) % 4; + for (int index2 = 0; value < this.padding; value = index2) { + index2++; + byteSequence.readByte(); + } + this.index = byteSequence.readInt(); + } + + @Override + public Object clone() throws CloneNotSupportedException { + Select select; + (select = (Select) super.clone()).match = (int[]) this.match.clone(); + select.indices = (int[]) this.indices.clone(); + select.targets = (InstructionHandle[]) this.targets.clone(); + return select; + } + + @Override + public boolean containsTarget(InstructionHandle instructionHandle) { + if (this.target == instructionHandle) { + return true; + } + int value; + for (int value2 = value = 0; value2 < this.targets.length; value2 = ++value) { + if (this.targets[value] == instructionHandle) { + return true; + } + } + return false; + } + + @Override + public int updatePosition(int count, int value2) { + this.count += count; + short value3 = this.length; + this.padding = (4 - (this.count + 1) % 4) % 4; + this.length = (short) (this.fixed_length + this.padding); + return this.length - value3; + } + + public int[] getMatch() { + return this.match; + } + + @Override + public void updateTarget( + InstructionHandle instructionHandle, InstructionHandle instructionHandle2) { + byte value = 0; + if (this.target == instructionHandle) { + value = 1; + this.setTarget(instructionHandle2); + } + int value2; + for (int value3 = value2 = 0; value3 < this.targets.length; value3 = ++value2) { + if (this.targets[value2] == instructionHandle) { + value = 1; + this.setTarget(value2, instructionHandle2); + } + } + if (value == 0) { + throw new ClassGenException(("Not targeting " + instructionHandle)); + } + } + + public Select( + short value, + int[] match, + InstructionHandle[] instructionHandles, + InstructionHandle instructionHandle) { + super(value, instructionHandle); + int value2 = 0; + this.padding = 0; + this.targets = instructionHandles; + for (int index = 0; value2 < instructionHandles.length; value2 = index) { + int value3 = index; + index++; + notifyTarget((InstructionHandle) (Object) null, instructionHandles[value3], this); + } + if ((this.match_length = (this.match = match).length) != instructionHandles.length) { + throw new ClassGenException("Match and target array have not the same length"); + } + this.indices = new int[this.match_length]; + } + + @Override + public void dispose() { + int value = 0; + super.dispose(); + for (int index = 0; value < this.targets.length; value = index) { + int value2 = index; + InstructionHandle[] instructionHandles = this.targets; + index++; + instructionHandles[value2].removeTargeter(this); + } + } + + public Select() {} +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/SimpleElementValueGen.java b/src/main/java/com/allatori/lib/bcel/generic/SimpleElementValueGen.java new file mode 100644 index 0000000..a0d3c81 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/SimpleElementValueGen.java @@ -0,0 +1,198 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.classfile.ConstantDouble; +import com.allatori.lib.bcel.classfile.ConstantFloat; +import com.allatori.lib.bcel.classfile.ConstantInteger; +import com.allatori.lib.bcel.classfile.ConstantLong; +import com.allatori.lib.bcel.classfile.ConstantUtf8; +import com.allatori.lib.bcel.classfile.ElementValue; +import com.allatori.lib.bcel.classfile.SimpleElementValue; +import java.io.DataOutputStream; +import java.io.IOException; + +public class SimpleElementValueGen extends ElementValueGen { + + public int idx; + + public SimpleElementValueGen(int value, int idx, ConstantPoolGen constantPoolGen) { + super(value, constantPoolGen); + this.idx = idx; + } + + @Override + public String stringifyValue() { + switch (this.type) { + case 66: + return Integer.toString(((ConstantInteger) this.cpGen.getConstant(this.idx)).getBytes()); + case 67: + return Integer.toString(((ConstantInteger) this.cpGen.getConstant(this.idx)).getBytes()); + case 68: + return Double.toString(((ConstantDouble) this.cpGen.getConstant(this.idx)).getBytes()); + case 70: + return Float.toString(((ConstantFloat) this.cpGen.getConstant(this.idx)).getBytes()); + case 73: + return Integer.toString(((ConstantInteger) this.cpGen.getConstant(this.idx)).getBytes()); + case 74: + return Long.toString(((ConstantLong) this.cpGen.getConstant(this.idx)).getBytes()); + case 83: + return Integer.toString(((ConstantInteger) this.cpGen.getConstant(this.idx)).getBytes()); + case 90: + ConstantInteger constantInteger; + if ((constantInteger = (ConstantInteger) this.cpGen.getConstant(this.idx)).getBytes() + == 0) { + return "false"; + } else if (constantInteger.getBytes() != 0) { + return "true"; + } + case 115: + return ((ConstantUtf8) this.cpGen.getConstant(this.idx)).getBytes(); + default: + throw new RuntimeException( + ("SimpleElementValueGen class does not know how to stringify type " + this.type)); + } + } + + public void setIdx(int idx) { + this.idx = idx; + } + + public SimpleElementValueGen(int value, ConstantPoolGen constantPoolGen, double value2) { + super(value, constantPoolGen); + this.idx = constantPoolGen.addDouble(value2); + } + + public SimpleElementValueGen(int value, ConstantPoolGen constantPoolGen, byte value2) { + super(value, constantPoolGen); + this.idx = constantPoolGen.addInteger(value2); + } + + @Override + public ElementValue getElementValue() { + return new SimpleElementValue(this.type, this.idx, this.cpGen.getConstantPool()); + } + + public SimpleElementValueGen(int value, ConstantPoolGen constantPoolGen, String text) { + super(value, constantPoolGen); + this.idx = constantPoolGen.addUtf8(text); + } + + public SimpleElementValueGen(int value, ConstantPoolGen constantPoolGen, boolean matches) { + super(value, constantPoolGen); + if (matches) { + this.idx = constantPoolGen.addInteger(1); + } else { + this.idx = constantPoolGen.addInteger(0); + } + } + + public int getIndex() { + return this.idx; + } + + public SimpleElementValueGen( + SimpleElementValue simpleElementValue, ConstantPoolGen constantPoolGen, boolean matches) { + super(simpleElementValue.getType(), constantPoolGen); + if (!matches) { + this.idx = simpleElementValue.getIndex(); + } else { + switch (simpleElementValue.getType()) { + case 66: + this.idx = constantPoolGen.addInteger(simpleElementValue.getValueByte()); + return; + case 67: + this.idx = constantPoolGen.addInteger(simpleElementValue.getValueChar()); + return; + case 68: + this.idx = constantPoolGen.addDouble(simpleElementValue.getValueDouble()); + return; + case 70: + this.idx = constantPoolGen.addFloat(simpleElementValue.getValueFloat()); + return; + case 73: + this.idx = constantPoolGen.addInteger(simpleElementValue.calculateCount()); + return; + case 74: + this.idx = constantPoolGen.addLong(simpleElementValue.getValueLong()); + return; + case 83: + this.idx = constantPoolGen.addInteger(simpleElementValue.getValueShort()); + return; + case 90: + if (simpleElementValue.getValueBoolean()) { + this.idx = constantPoolGen.addInteger(1); + return; + } + this.idx = constantPoolGen.addInteger(0); + return; + case 115: + this.idx = constantPoolGen.addUtf8(simpleElementValue.createText2()); + return; + default: + throw new RuntimeException( + ("SimpleElementValueGen class does not know how to copy this type " + this.type)); + } + } + } + + public SimpleElementValueGen(int value, ConstantPoolGen constantPoolGen, char value2) { + super(value, constantPoolGen); + this.idx = constantPoolGen.addInteger(value2); + } + + public SimpleElementValueGen(int value, ConstantPoolGen constantPoolGen, long value2) { + super(value, constantPoolGen); + this.idx = constantPoolGen.addLong(value2); + } + + public SimpleElementValueGen(int value, ConstantPoolGen constantPoolGen, short value2) { + super(value, constantPoolGen); + this.idx = constantPoolGen.addInteger(value2); + } + + public String getValueString() { + if (this.type != 115) { + throw new RuntimeException("Dont call getValueString() on a non STRING ElementValue"); + } else { + return ((ConstantUtf8) this.cpGen.getConstant(this.idx)).getBytes(); + } + } + + public SimpleElementValueGen(int value, ConstantPoolGen constantPoolGen, float value2) { + super(value, constantPoolGen); + this.idx = constantPoolGen.addFloat(value2); + } + + public SimpleElementValueGen(int value, ConstantPoolGen constantPoolGen, int value2) { + super(value, constantPoolGen); + this.idx = constantPoolGen.addInteger(value2); + } + + public int getValueInt() { + if (this.type != 73) { + throw new RuntimeException("Dont call getValueString() on a non STRING ElementValue"); + } else { + return ((ConstantInteger) this.cpGen.getConstant(this.idx)).getBytes(); + } + } + + @Override + public void dump(DataOutputStream dataOutputStream) throws IOException { + dataOutputStream.writeByte(this.type); + switch (this.type) { + case 66: + case 67: + case 68: + case 70: + case 73: + case 74: + case 83: + case 90: + case 115: + dataOutputStream.writeShort(this.idx); + return; + default: + throw new RuntimeException( + ("SimpleElementValueGen doesnt know how to write out type " + this.type)); + } + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/StackConsumer.java b/src/main/java/com/allatori/lib/bcel/generic/StackConsumer.java new file mode 100644 index 0000000..99bc782 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/StackConsumer.java @@ -0,0 +1,6 @@ +package com.allatori.lib.bcel.generic; + +public interface StackConsumer { + + int consumeStack(ConstantPoolGen constantPoolGen); +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/StackInstruction.java b/src/main/java/com/allatori/lib/bcel/generic/StackInstruction.java new file mode 100644 index 0000000..fdc2fb2 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/StackInstruction.java @@ -0,0 +1,14 @@ +package com.allatori.lib.bcel.generic; + +public abstract class StackInstruction extends Instruction { + + public Type getType(ConstantPoolGen constantPoolGen) { + return Type.UNKNOWN; + } + + public StackInstruction() {} + + public StackInstruction(short value) { + super(value, (short) 1); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/StackProducer.java b/src/main/java/com/allatori/lib/bcel/generic/StackProducer.java new file mode 100644 index 0000000..2874101 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/StackProducer.java @@ -0,0 +1,6 @@ +package com.allatori.lib.bcel.generic; + +public interface StackProducer { + + int produceStack(ConstantPoolGen constantPoolGen); +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/StoreInstruction.java b/src/main/java/com/allatori/lib/bcel/generic/StoreInstruction.java new file mode 100644 index 0000000..4295fbf --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/StoreInstruction.java @@ -0,0 +1,21 @@ +package com.allatori.lib.bcel.generic; + +public abstract class StoreInstruction extends LocalVariableInstruction implements PopInstruction { + + public StoreInstruction(short value, short value2, int value3) { + super(value, value2, value3); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitStackConsumer(this); + visitor.visitPopInstruction(this); + visitor.visitTypedInstruction(this); + visitor.visitLocalVariableInstruction(this); + visitor.visitStoreInstruction(this); + } + + public StoreInstruction(short value, short value2) { + super(value, value2); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/TABLESWITCH.java b/src/main/java/com/allatori/lib/bcel/generic/TABLESWITCH.java new file mode 100644 index 0000000..7f18b4d --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/TABLESWITCH.java @@ -0,0 +1,74 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.util.ByteSequence; +import java.io.DataOutputStream; +import java.io.IOException; + +public class TABLESWITCH extends Select { + + public TABLESWITCH() {} + + public TABLESWITCH( + int[] values, InstructionHandle[] instructionHandles, InstructionHandle instructionHandle) { + super((short) 170, values, instructionHandles, instructionHandle); + this.length = (short) (13 + this.match_length * 4); + this.fixed_length = this.length; + } + + @Override + public void dump(DataOutputStream dataOutputStream) throws IOException { + super.dump(dataOutputStream); + int value = this.match_length > 0 ? this.match[0] : 0; + dataOutputStream.writeInt(value); + int value2 = this.match_length > 0 ? this.match[this.match_length - 1] : 0; + int value3 = 0; + dataOutputStream.writeInt(value2); + for (int index = 0; value3 < this.match_length; value3 = index) { + int[] values = this.indices; + int value4; + int value5 = value4 = this.getTargetOffset(this.targets[index]); + int value6 = index; + index++; + values[value6] = value4; + dataOutputStream.writeInt(value5); + } + } + + @Override + public void accept(Visitor visitor) { + visitor.visitVariableLengthInstruction(this); + visitor.visitStackProducer(this); + visitor.visitBranchInstruction(this); + visitor.visitSelect(this); + visitor.visitTABLESWITCH(this); + } + + @Override + public void initFromFile(ByteSequence byteSequence, boolean matches) throws IOException { + super.initFromFile(byteSequence, matches); + int value = byteSequence.readInt(); + int value2; + this.match_length = (value2 = byteSequence.readInt()) - value + 1; + this.fixed_length = (short) (13 + this.match_length * 4); + this.length = (short) (this.fixed_length + this.padding); + this.match = new int[this.match_length]; + this.indices = new int[this.match_length]; + this.targets = new InstructionHandle[this.match_length]; + int value3; + for (int value4 = value3 = value; value4 <= value2; value4 = value3) { + int value5 = value3 - value; + int value6 = value3; + int[] values = this.match; + value3++; + values[value5] = value6; + } + int value7; + for (int value8 = value7 = 0; value8 < this.match_length; value8 = value7) { + int[] values2 = this.indices; + int value9 = byteSequence.readInt(); + int value10 = value7; + value7++; + values2[value10] = value9; + } + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/TargetLostException.java b/src/main/java/com/allatori/lib/bcel/generic/TargetLostException.java new file mode 100644 index 0000000..5567d65 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/TargetLostException.java @@ -0,0 +1,15 @@ +package com.allatori.lib.bcel.generic; + +public final class TargetLostException extends Exception { + + public InstructionHandle[] targets; + + public TargetLostException(InstructionHandle[] instructionHandles, String text) { + super(text); + this.targets = instructionHandles; + } + + public InstructionHandle[] getTargets() { + return this.targets; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/Type$1.java b/src/main/java/com/allatori/lib/bcel/generic/Type$1.java new file mode 100644 index 0000000..e624114 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/Type$1.java @@ -0,0 +1,3 @@ +package com.allatori.lib.bcel.generic; + +public class Type$1 extends ReferenceType {} diff --git a/src/main/java/com/allatori/lib/bcel/generic/Type$2.java b/src/main/java/com/allatori/lib/bcel/generic/Type$2.java new file mode 100644 index 0000000..f4aff25 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/Type$2.java @@ -0,0 +1,8 @@ +package com.allatori.lib.bcel.generic; + +public class Type$2 extends Type { + + public Type$2(byte value, String text) { + super(value, text); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/Type.java b/src/main/java/com/allatori/lib/bcel/generic/Type.java new file mode 100644 index 0000000..a33a116 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/Type.java @@ -0,0 +1,286 @@ +package com.allatori.lib.bcel.generic; + +import com.allatori.lib.bcel.classfile.ClassFormatException; +import com.allatori.lib.bcel.classfile.Utility; +import com.allatori.lib.bcel.util.TypeParserThreadLocal; +import java.io.Serializable; +import java.lang.reflect.Method; +import java.util.ArrayList; + +public abstract class Type implements Serializable { + + public static final BasicType VOID = new BasicType((byte) 12); + + public static final BasicType BOOLEAN = new BasicType((byte) 4); + + public static final BasicType INT = new BasicType((byte) 10); + + public static final BasicType SHORT = new BasicType((byte) 9); + + public static final BasicType BYTE = new BasicType((byte) 8); + + public static final BasicType LONG = new BasicType((byte) 11); + + public static final BasicType DOUBLE = new BasicType((byte) 7); + + public static final BasicType FLOAT = new BasicType((byte) 6); + + public static final BasicType CHAR = new BasicType((byte) 5); + + public static final ObjectType OBJECT = new ObjectType("java.lang.Object"); + + public static final ObjectType CLASS = new ObjectType("java.lang.Class"); + + public static final ObjectType STRING = new ObjectType("java.lang.String"); + + public static final ObjectType STRINGBUFFER = new ObjectType("java.lang.StringBuffer"); + + public static final ObjectType THROWABLE = new ObjectType("java.lang.Throwable"); + + public static final Type[] NO_ARGS = new Type[0]; + + public static final ReferenceType NULL = new Type$1(); + + public static final Type UNKNOWN = new Type$2((byte) 15, ""); + + public static ThreadLocal consumed_chars = new TypeParserThreadLocal(); + + public byte type; + + public String signature; + + public static int calculateCount(String text) { + return calculateCount2(calculateCount3(text.substring(text.lastIndexOf(41) + 1))); + } + + public static Type getType(Class classValue) { + if (classValue == null) { + throw new IllegalArgumentException("Class must not be null"); + } + if (classValue.isArray()) { + return getType(classValue.getName()); + } + if (classValue.isPrimitive()) { + if (classValue == int.class) { + return INT; + } else if (classValue == void.class) { + return VOID; + } else if (classValue == double.class) { + return DOUBLE; + } else if (classValue == float.class) { + return FLOAT; + } else if (classValue == boolean.class) { + return BOOLEAN; + } else if (classValue == byte.class) { + return BYTE; + } else if (classValue == short.class) { + return SHORT; + } else if (classValue == byte.class) { + return BYTE; + } else if (classValue == long.class) { + return LONG; + } else if (classValue == char.class) { + return CHAR; + } else { + throw new IllegalStateException(("Ooops, what primitive type is " + classValue)); + } + } else { + return new ObjectType(classValue.getName()); + } + } + + public static int encode(int value, int value2) { + return value2 << 2 | value; + } + + public static String getMethodSignature(Type type, Type[] types) { + StringBuffer stringBuffer = new StringBuffer("("); + int value = types == null ? 0 : types.length; + int value2; + for (int value3 = value2 = 0; value3 < value; value3 = value2) { + int value4 = value2; + value2++; + stringBuffer.append(types[value4].getSignature()); + } + stringBuffer.append(')'); + stringBuffer.append(type.getSignature()); + return stringBuffer.toString(); + } + + public static String getSignature(Method method) { + StringBuffer stringBuffer = new StringBuffer("("); + Class[] parameterTypes = method.getParameterTypes(); + int value; + for (int value2 = value = 0; value2 < parameterTypes.length; value2 = value) { + Class classValue = parameterTypes[value]; + value++; + stringBuffer.append(getType(classValue).getSignature()); + } + stringBuffer.append(")"); + stringBuffer.append(getType(method.getReturnType()).getSignature()); + return stringBuffer.toString(); + } + + public static int calculateCount2(String text) { + int value = 0; + try { + if (text.charAt(0) != '(') { + throw new ClassFormatException(("Invalid method signature: " + text)); + } + int value2 = 1; + while (text.charAt(value2) != ')') { + int value3 = calculateCount3(text.substring(value2)); + value += calculateCount2(value3); + value2 += calculateCount(value3); + } + return value; + } catch (StringIndexOutOfBoundsException stringIndexOutOfBoundsException) { + throw new ClassFormatException( + ("Invalid method signature: " + text), stringIndexOutOfBoundsException); + } + } + + public int getSize() { + switch (this.type) { + case 7: + case 11: + return 2; + case 12: + return 0; + default: + return 1; + } + } + + public static int calculateCount(int value) { + return value >> 2; + } + + public static Type getReturnType(String text) { + try { + return getType(text.substring(text.lastIndexOf(41) + 1)); + } catch (StringIndexOutOfBoundsException stringIndexOutOfBoundsException) { + throw new ClassFormatException(("Invalid method signature: " + text)); + } + } + + public static void wrap(ThreadLocal threadLocal, int value) { + threadLocal.set(new Integer(value)); + } + + public static int unwrap(ThreadLocal threadLocal) { + return (Integer) threadLocal.get(); + } + + public byte getType() { + return this.type; + } + + public Type(byte type, String signature) { + super(); + this.type = type; + this.signature = signature; + } + + public static int calculateCount3(String text) { + byte value; + if ((value = Utility.calculateValue2(text)) <= 12) { + return encode(BasicType.getType(value).getSize(), 1); + } + if (value != 13) { + int value2; + if ((value2 = text.indexOf(59)) < 0) { + throw new ClassFormatException(("Invalid signature: " + text)); + } else { + return encode(1, value2 + 1); + } + } else { + int value3 = 0; + while (text.charAt(++value3) == '[') {} + int value4 = calculateCount(calculateCount3(text.substring(value3))); + return encode(1, value3 + value4); + } + } + + public static Type[] getArgumentTypes(String text) { + ArrayList values = new ArrayList(); + try { + if (text.charAt(0) != '(') { + throw new ClassFormatException(("Invalid method signature: " + text)); + } + for (int index = 1; text.charAt(index) != ')'; index += unwrap(consumed_chars)) { + values.add(getType(text.substring(index))); + } + } catch (StringIndexOutOfBoundsException stringIndexOutOfBoundsException) { + throw new ClassFormatException(("Invalid method signature: " + text)); + } + Type[] types = new Type[values.size()]; + values.toArray(types); + return types; + } + + public static int calculateCount2(int value) { + return value & 3; + } + + public static final Type getType(String text) throws StringIndexOutOfBoundsException { + byte value; + if ((value = Utility.calculateValue2(text)) <= 12) { + wrap(consumed_chars, 1); + return BasicType.getType(value); + } + if (value != 13) { + int value2; + if ((value2 = text.indexOf(59)) < 0) { + throw new ClassFormatException(("Invalid signature: " + text)); + } + wrap(consumed_chars, value2 + 1); + return new ObjectType(text.substring(1, value2).replace('/', '.')); + } else { + int value3 = 0; + while (text.charAt(++value3) == '[') {} + Type type = getType(text.substring(value3)); + int value4 = unwrap(consumed_chars) + value3; + wrap(consumed_chars, value4); + return new ArrayType(type, value3); + } + } + + @Override + public boolean equals(Object result) { + if (result instanceof Type) { + Type type2 = (Type) result; + return this.type == type2.type && this.signature.equals(type2.signature); + } else { + return false; + } + } + + @Override + public String toString() { + return !this.equals(NULL) && this.type < 15 + ? Utility.signatureToString(this.signature, false) + : this.signature; + } + + @Override + public int hashCode() { + return this.type ^ this.signature.hashCode(); + } + + public String getSignature() { + return this.signature; + } + + public static Type[] getTypes(Class[] classs) { + Type[] types = new Type[classs.length]; + int value; + for (int value2 = value = 0; value2 < types.length; value2 = value) { + Type type = getType(classs[value]); + int value3 = value; + value++; + types[value3] = type; + } + return types; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/TypedInstruction.java b/src/main/java/com/allatori/lib/bcel/generic/TypedInstruction.java new file mode 100644 index 0000000..ff01c3e --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/TypedInstruction.java @@ -0,0 +1,6 @@ +package com.allatori.lib.bcel.generic; + +public interface TypedInstruction { + + Type getType(ConstantPoolGen constantPoolGen); +} diff --git a/src/main/java/com/allatori/lib/bcel/generic/UnconditionalBranch.java b/src/main/java/com/allatori/lib/bcel/generic/UnconditionalBranch.java new file mode 100644 index 0000000..7303901 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/UnconditionalBranch.java @@ -0,0 +1,3 @@ +package com.allatori.lib.bcel.generic; + +public interface UnconditionalBranch {} diff --git a/src/main/java/com/allatori/lib/bcel/generic/VariableLengthInstruction.java b/src/main/java/com/allatori/lib/bcel/generic/VariableLengthInstruction.java new file mode 100644 index 0000000..15f05cc --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/VariableLengthInstruction.java @@ -0,0 +1,3 @@ +package com.allatori.lib.bcel.generic; + +public interface VariableLengthInstruction {} diff --git a/src/main/java/com/allatori/lib/bcel/generic/Visitor.java b/src/main/java/com/allatori/lib/bcel/generic/Visitor.java new file mode 100644 index 0000000..a499994 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/generic/Visitor.java @@ -0,0 +1,364 @@ +package com.allatori.lib.bcel.generic; + +public interface Visitor { + + void visitFLOAD(FLOAD fLOAD); + + void visitIOR(IOR oR); + + void visitIFGT(IFGT fGT); + + void visitStoreInstruction(StoreInstruction storeInstruction); + + void visitSASTORE(SASTORE sASTORE); + + void visitDDIV(DDIV dDIV); + + void visitDCMPG(DCMPG dCMPG); + + void visitCPInstruction(CPInstruction cPInstruction); + + void visitFASTORE(FASTORE fASTORE); + + void visitIF_ACMPNE(IF_ACMPNE f_ACMPNE); + + void visitFieldOrMethod(FieldOrMethod fieldOrMethod); + + void visitLCMP(LCMP lCMP); + + void visitCASTORE(CASTORE cASTORE); + + void visitIDIV(IDIV dIV); + + void visitDCONST(DCONST dCONST); + + void visitI2L(I2L i2L); + + void visitANEWARRAY(ANEWARRAY aNEWARRAY); + + void visitMONITORENTER(MONITORENTER mONITORENTER); + + void visitFCMPG(FCMPG fCMPG); + + void visitFRETURN(FRETURN fRETURN); + + void visitFALOAD(FALOAD fALOAD); + + void visitICONST(ICONST cONST); + + void visitLNEG(LNEG lNEG); + + void visitConversionInstruction(ConversionInstruction conversionInstruction); + + void visitPopInstruction(PopInstruction popInstruction); + + void visitI2F(I2F i2F); + + void visitBranchInstruction(BranchInstruction branchInstruction); + + void visitIFNE(IFNE fNE); + + void visitPushInstruction(PushInstruction pushInstruction); + + void visitIMPDEP1(IMPDEP1 mPDEP1); + + void visitIMPDEP2(IMPDEP2 mPDEP2); + + void visitF2D(F2D f2D); + + void visitLOOKUPSWITCH(LOOKUPSWITCH lOOKUPSWITCH); + + void visitIF_ICMPGT(IF_ICMPGT f_ICMPGT); + + void visitISHL(ISHL sHL); + + void visitDMUL(DMUL dMUL); + + void visitFSTORE(FSTORE fSTORE); + + void visitSelect(Select select); + + void visitIF_ICMPLE(IF_ICMPLE f_ICMPLE); + + void visitDUP_X1(DUP_X1 dUP_X1); + + void visitBALOAD(BALOAD bALOAD); + + void visitRETURN(RETURN rETURN); + + void visitACONST_NULL(ACONST_NULL aCONST_NULL); + + void visitIMUL(IMUL mUL); + + void visitIF_ICMPEQ(IF_ICMPEQ f_ICMPEQ); + + void visitDLOAD(DLOAD dLOAD); + + void visitALOAD(ALOAD aLOAD); + + void visitPUTSTATIC(PUTSTATIC pUTSTATIC); + + void visitINVOKEVIRTUAL(INVOKEVIRTUAL nVOKEVIRTUAL); + + void visitLoadInstruction(LoadInstruction loadInstruction); + + void visitISTORE(ISTORE sTORE); + + void visitNOP(NOP nOP); + + void visitGotoInstruction(GotoInstruction gotoInstruction); + + void visitSIPUSH(SIPUSH sIPUSH); + + void visitIXOR(IXOR xOR); + + void visitIF_ICMPNE(IF_ICMPNE f_ICMPNE); + + void visitI2D(I2D i2D); + + void visitLSHL(LSHL lSHL); + + void visitCHECKCAST(CHECKCAST cHECKCAST); + + void visitD2I(D2I d2I); + + void visitINVOKESPECIAL(INVOKESPECIAL nVOKESPECIAL); + + void visitIFLT(IFLT fLT); + + void visitJsrInstruction(JsrInstruction jsrInstruction); + + void visitGETFIELD(GETFIELD gETFIELD); + + void visitStackProducer(StackProducer stackProducer); + + void visitLSTORE(LSTORE lSTORE); + + void visitStackConsumer(StackConsumer stackConsumer); + + void visitMULTIANEWARRAY(MULTIANEWARRAY mULTIANEWARRAY); + + void visitASTORE(ASTORE aSTORE); + + void visitIFEQ(IFEQ fEQ); + + void visitINVOKEINTERFACE(INVOKEINTERFACE nVOKEINTERFACE); + + void visitArithmeticInstruction(ArithmeticInstruction arithmeticInstruction); + + void visitIFLE(IFLE fLE); + + void visitPUTFIELD(PUTFIELD pUTFIELD); + + void visitBREAKPOINT(BREAKPOINT bREAKPOINT); + + void visitLDC2_W(LDC2_W lDC2_W); + + void visitNEW(NEW nEW); + + void visitVariableLengthInstruction(VariableLengthInstruction variableLengthInstruction); + + void visitI2C(I2C i2C); + + void visitF2I(F2I f2I); + + void visitDUP_X2(DUP_X2 dUP_X2); + + void visitLOR(LOR lOR); + + void visitLCONST(LCONST lCONST); + + void visitConstantPushInstruction(ConstantPushInstruction constantPushInstruction); + + void visitIF_ICMPGE(IF_ICMPGE f_ICMPGE); + + void visitDRETURN(DRETURN dRETURN); + + void visitFMUL(FMUL fMUL); + + void visitDREM(DREM dREM); + + void visitLocalVariableInstruction(LocalVariableInstruction localVariableInstruction); + + void visitGETSTATIC(GETSTATIC gETSTATIC); + + void visitISHR(ISHR sHR); + + void visitInvokeInstruction(InvokeInstruction invokeInstruction); + + void visitFSUB(FSUB fSUB); + + void visitIINC(IINC iNC); + + void visitTypedInstruction(TypedInstruction typedInstruction); + + void visitDADD(DADD dADD); + + void visitIUSHR(IUSHR uSHR); + + void visitLASTORE(LASTORE lASTORE); + + void visitL2I(L2I l2I); + + void visitI2B(I2B i2B); + + void visitL2D(L2D l2D); + + void visitI2S(I2S i2S); + + void visitTABLESWITCH(TABLESWITCH tABLESWITCH); + + void visitINVOKESTATIC(INVOKESTATIC nVOKESTATIC); + + void visitUnconditionalBranch(UnconditionalBranch unconditionalBranch); + + void visitLADD(LADD lADD); + + void visitFREM(FREM fREM); + + void visitISUB(ISUB sUB); + + void visitIF_ICMPLT(IF_ICMPLT f_ICMPLT); + + void visitFNEG(FNEG fNEG); + + void visitD2L(D2L d2L); + + void visitAASTORE(AASTORE aASTORE); + + void visitSALOAD(SALOAD sALOAD); + + void visitGOTO(GOTO gOTO); + + void visitLMUL(LMUL lMUL); + + void visitStackInstruction(StackInstruction stackInstruction); + + void visitAllocationInstruction(AllocationInstruction allocationInstruction); + + void visitFCONST(FCONST fCONST); + + void visitDCMPL(DCMPL dCMPL); + + void visitL2F(L2F l2F); + + void visitLoadClass(LoadClass loadClass); + + void visitDUP2_X2(DUP2_X2 dUP2_X2); + + void visitFCMPL(FCMPL fCMPL); + + void visitDUP2(DUP2 dUP2); + + void visitJSR(JSR jSR); + + void visitIFNONNULL(IFNONNULL fNONNULL); + + void visitReturnInstruction(ReturnInstruction returnInstruction); + + void visitSWAP(SWAP sWAP); + + void visitLALOAD(LALOAD lALOAD); + + void visitLSHR(LSHR lSHR); + + void visitIfInstruction(IfInstruction ifInstruction); + + void visitIRETURN(IRETURN rETURN); + + void visitDUP2_X1(DUP2_X1 dUP2_X1); + + void visitIAND(IAND aND); + + void visitArrayInstruction(ArrayInstruction arrayInstruction); + + void visitLDIV(LDIV lDIV); + + void visitNEWARRAY(NEWARRAY nEWARRAY); + + void visitARRAYLENGTH(ARRAYLENGTH aRRAYLENGTH); + + void visitLREM(LREM lREM); + + void visitLLOAD(LLOAD lLOAD); + + void visitRET(RET rET); + + void visitIFGE(IFGE fGE); + + void visitPOP(POP pOP); + + void visitDSTORE(DSTORE dSTORE); + + void visitExceptionThrower(ExceptionThrower exceptionThrower); + + void visitFADD(FADD fADD); + + void visitLDC(LDC lDC); + + void visitD2F(D2F d2F); + + void visitLRETURN(LRETURN lRETURN); + + void visitLUSHR(LUSHR lUSHR); + + void visitJSR_W(JSR_W jSR_W); + + void visitBIPUSH(BIPUSH bIPUSH); + + void visitFieldInstruction(FieldInstruction fieldInstruction); + + void visitPOP2(POP2 pOP2); + + void visitFDIV(FDIV fDIV); + + void visitLXOR(LXOR lXOR); + + void visitATHROW(ATHROW aTHROW); + + void visitIADD(IADD aDD); + + void visitIREM(IREM rEM); + + void visitDUP(DUP dUP); + + void visitILOAD(ILOAD lOAD); + + void visitIASTORE(IASTORE aSTORE); + + void visitCALOAD(CALOAD cALOAD); + + void visitDSUB(DSUB dSUB); + + void visitDASTORE(DASTORE dASTORE); + + void visitINEG(INEG nEG); + + void visitDALOAD(DALOAD dALOAD); + + void visitMONITOREXIT(MONITOREXIT mONITOREXIT); + + void visitGOTO_W(GOTO_W gOTO_W); + + void visitINSTANCEOF(INSTANCEOF nSTANCEOF); + + void visitBASTORE(BASTORE bASTORE); + + void visitLSUB(LSUB lSUB); + + void visitDNEG(DNEG dNEG); + + void visitAALOAD(AALOAD aALOAD); + + void visitIALOAD(IALOAD aLOAD); + + void visitLAND(LAND lAND); + + void visitIFNULL(IFNULL fNULL); + + void visitARETURN(ARETURN aRETURN); + + void visitF2L(F2L f2L); + + void visitIF_ACMPEQ(IF_ACMPEQ f_ACMPEQ); +} diff --git a/src/main/java/com/allatori/lib/bcel/util/AttributeHTML.java b/src/main/java/com/allatori/lib/bcel/util/AttributeHTML.java new file mode 100644 index 0000000..826cdf5 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/util/AttributeHTML.java @@ -0,0 +1,292 @@ +package com.allatori.lib.bcel.util; + +import com.allatori.lib.bcel.Constants; +import com.allatori.lib.bcel.classfile.Attribute; +import com.allatori.lib.bcel.classfile.Code; +import com.allatori.lib.bcel.classfile.CodeException; +import com.allatori.lib.bcel.classfile.ConstantPool; +import com.allatori.lib.bcel.classfile.ConstantUtf8; +import com.allatori.lib.bcel.classfile.ConstantValue; +import com.allatori.lib.bcel.classfile.ExceptionTable; +import com.allatori.lib.bcel.classfile.InnerClass; +import com.allatori.lib.bcel.classfile.InnerClasses; +import com.allatori.lib.bcel.classfile.LineNumber; +import com.allatori.lib.bcel.classfile.LineNumberTable; +import com.allatori.lib.bcel.classfile.LocalVariable; +import com.allatori.lib.bcel.classfile.LocalVariableTable; +import com.allatori.lib.bcel.classfile.SourceFile; +import com.allatori.lib.bcel.classfile.Utility; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintWriter; + +public final class AttributeHTML implements Constants { + + public int attr_count; + + public ConstantPool constant_pool; + + public String class_name; + + public ConstantHTML constant_html; + + public PrintWriter file; + + public final void writeAttribute(Attribute attribute, String text) throws IOException { + this.writeAttribute(attribute, text, 0); + } + + public final String codeLink(int value, int value2) { + return "" + + value + + ""; + } + + public AttributeHTML( + String text, String class_name, ConstantPool constantPool, ConstantHTML constantHTML) + throws IOException { + super(); + this.attr_count = 0; + this.class_name = class_name; + this.constant_pool = constantPool; + this.constant_html = constantHTML; + this.file = + new PrintWriter(new FileOutputStream(("" + text + class_name + "_attributes.html"))); + this.file.println(""); + } + + public final void writeAttribute(Attribute attribute, String text, int value) throws IOException { + byte value2; + if ((value2 = attribute.getTag()) != -1) { + this.attr_count++; + AttributeHTML attributeHTML; + if (this.attr_count % 2 == 0) { + attributeHTML = this; + this.file.print(""); + this.file.flush(); + } + } + + public final void close() { + this.file.println("
"); + } else { + attributeHTML = this; + this.file.print("
"); + } + label82: + { + attributeHTML.file.println( + "

" + this.attr_count + " " + TEXTS4[value2] + "

"); + switch (value2) { + case 0: + int sourceFileIndex = ((SourceFile) attribute).getSourceFileIndex(); + PrintWriter printWriter = this.file; + StringBuilder stringBuilder = new StringBuilder().insert(0, "\n") + .toString()); + break label82; + case 1: + int constantValueIndex = ((ConstantValue) attribute).getConstantValueIndex(); + PrintWriter printWriter2 = this.file; + StringBuilder stringBuilder2 = new StringBuilder().insert(0, "\n") + .toString()); + break label82; + case 2: + Code code = (Code) attribute; + this.file.print( + "
  • Maximum stack size = " + + code.getMax_stack() + + "
  • \n
  • Number of local variables = " + + code.getMax_locals() + + "
  • \n
  • Byte code
\n"); + CodeException[] codeExceptions; + int value3; + if ((value3 = (codeExceptions = code.getExceptionTable()).length) > 0) { + int value4 = 0; + this.file.print("

Exceptions handled

    "); + for (int index = 0; value4 < value3; value4 = index) { + int catch_type = codeExceptions[index].getCatch_type(); + this.file.print("
  • "); + if (catch_type != 0) { + this.file.print(this.constant_html.referenceConstant(catch_type)); + attributeHTML = this; + } else { + this.file.print("Any Exception"); + attributeHTML = this; + } + PrintWriter printWriter3 = attributeHTML.file; + StringBuilder stringBuilder3 = + new StringBuilder() + .insert(0, "
    (Ranging from lines ") + .append(this.codeLink(codeExceptions[index].getStart_pc(), value)) + .append(" to ") + .append(this.codeLink(codeExceptions[index].getEnd_pc(), value)) + .append(", handled at line ") + .append(this.codeLink(codeExceptions[index].getHandler_pc(), value)); + index++; + printWriter3.print(stringBuilder3.append((String) ")
  • ").toString()); + } + attributeHTML = this; + this.file.print("
"); + break label82; + } + break; + case 3: + int[] exceptionIndexTable = ((ExceptionTable) attribute).getExceptionIndexTable(); + int value5 = 0; + this.file.print("\n"); + break label82; + case 4: + LineNumber[] lineNumberTable = ((LineNumberTable) attribute).getLineNumberTable(); + int value6 = 0; + this.file.print("

"); + for (int index3 = 0; value6 < lineNumberTable.length; value6 = ++index3) { + this.file.print( + "(" + + lineNumberTable[index3].getStart_pc() + + ", " + + lineNumberTable[index3].getLine_number() + + ")"); + if (index3 < lineNumberTable.length - 1) { + this.file.print(", "); + } + } + break; + case 5: + LocalVariable[] localVariableTable = + ((LocalVariableTable) attribute).getLocalVariableTable(); + int value7 = 0; + this.file.print("

    "); + for (int index4 = 0; value7 < localVariableTable.length; value7 = index4) { + int signature_index = localVariableTable[index4].getSignature_index(); + String text2 = + Utility.signatureToString( + ((ConstantUtf8) this.constant_pool.getConstant(signature_index, (byte) 1)) + .getBytes(), + false); + int value8; + int value9 = + (value8 = localVariableTable[index4].getStart_pc()) + + localVariableTable[index4].getLength(); + PrintWriter printWriter5 = this.file; + StringBuilder stringBuilder5 = + new StringBuilder() + .insert(0, "
  • ") + .append(Class2HTML.createText(text2)) + .append(" ") + .append(localVariableTable[index4].getText()) + .append(" in slot %") + .append(localVariableTable[index4].getIndex()) + .append("
    Valid from lines ") + .append("") + .append(value8) + .append(" to ") + .append("") + .append(value9); + index4++; + printWriter5.println(stringBuilder5.append((String) "
  • ").toString()); + } + attributeHTML = this; + this.file.print("
\n"); + break label82; + case 6: + InnerClass[] innerClasses = ((InnerClasses) attribute).getInnerClasses(); + int value10 = 0; + this.file.print("
    "); + for (int index5 = 0; value10 < innerClasses.length; value10 = index5) { + String text3; + int value11; + InnerClass[] innerClasss; + if ((value11 = innerClasses[index5].getInner_name_index()) > 0) { + text3 = + ((ConstantUtf8) this.constant_pool.getConstant(value11, (byte) 1)).getBytes(); + innerClasss = innerClasses; + } else { + text3 = "<anonymous>"; + innerClasss = innerClasses; + } + String text22 = Utility.getText2(innerClasss[index5].getInner_access_flags()); + PrintWriter printWriter6 = this.file; + StringBuilder stringBuilder6 = + new StringBuilder() + .insert(0, "
  • ") + .append(text22) + .append(" ") + .append( + this.constant_html.referenceConstant( + innerClasses[index5].getInner_class_index())) + .append(" in class ") + .append( + this.constant_html.referenceConstant( + innerClasses[index5].getOuter_class_index())) + .append(" named ") + .append(text3); + index5++; + printWriter6.print(stringBuilder6.append((String) "
  • \n").toString()); + } + attributeHTML = this; + this.file.print("
\n"); + break label82; + default: + this.file.print("

" + attribute.toString()); + } + attributeHTML = this; + } + attributeHTML.file.println("

"); + this.file.close(); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/util/BCELComparator.java b/src/main/java/com/allatori/lib/bcel/util/BCELComparator.java new file mode 100644 index 0000000..b4c081c --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/util/BCELComparator.java @@ -0,0 +1,8 @@ +package com.allatori.lib.bcel.util; + +public interface BCELComparator { + + int hashCode(Object result); + + boolean equals(Object result, Object result2); +} diff --git a/src/main/java/com/allatori/lib/bcel/util/BCELFactory.java b/src/main/java/com/allatori/lib/bcel/util/BCELFactory.java new file mode 100644 index 0000000..720a29d --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/util/BCELFactory.java @@ -0,0 +1,397 @@ +package com.allatori.lib.bcel.util; + +import com.allatori.lib.bcel.Constants; +import com.allatori.lib.bcel.classfile.Utility; +import com.allatori.lib.bcel.generic.AllocationInstruction; +import com.allatori.lib.bcel.generic.ArrayInstruction; +import com.allatori.lib.bcel.generic.ArrayType; +import com.allatori.lib.bcel.generic.BranchHandle; +import com.allatori.lib.bcel.generic.BranchInstruction; +import com.allatori.lib.bcel.generic.CHECKCAST; +import com.allatori.lib.bcel.generic.CPInstruction; +import com.allatori.lib.bcel.generic.CodeExceptionGen; +import com.allatori.lib.bcel.generic.ConstantPoolGen; +import com.allatori.lib.bcel.generic.ConstantPushInstruction; +import com.allatori.lib.bcel.generic.EmptyVisitor; +import com.allatori.lib.bcel.generic.FieldInstruction; +import com.allatori.lib.bcel.generic.IINC; +import com.allatori.lib.bcel.generic.INSTANCEOF; +import com.allatori.lib.bcel.generic.Instruction; +import com.allatori.lib.bcel.generic.InstructionConstants; +import com.allatori.lib.bcel.generic.InstructionHandle; +import com.allatori.lib.bcel.generic.InvokeInstruction; +import com.allatori.lib.bcel.generic.LDC; +import com.allatori.lib.bcel.generic.LDC2_W; +import com.allatori.lib.bcel.generic.LocalVariableInstruction; +import com.allatori.lib.bcel.generic.MULTIANEWARRAY; +import com.allatori.lib.bcel.generic.MethodGen; +import com.allatori.lib.bcel.generic.NEWARRAY; +import com.allatori.lib.bcel.generic.ObjectType; +import com.allatori.lib.bcel.generic.RET; +import com.allatori.lib.bcel.generic.ReturnInstruction; +import com.allatori.lib.bcel.generic.Select; +import com.allatori.lib.bcel.generic.Type; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +public class BCELFactory extends EmptyVisitor { + + public MethodGen _mg; + + public List branches; + + public Map branch_map; + + public ConstantPoolGen _cp; + + public PrintWriter _out; + + public BCELFactory(MethodGen methodGen, PrintWriter printWriter) { + super(); + this.branch_map = new HashMap(); + this.branches = new ArrayList(); + this._mg = methodGen; + this._cp = methodGen.getConstantPool(); + this._out = printWriter; + } + + @Override + public void visitAllocationInstruction(AllocationInstruction allocationInstruction) { + Type type; + AllocationInstruction allocationInstruction2; + if (allocationInstruction instanceof CPInstruction) { + type = ((CPInstruction) allocationInstruction).getType(this._cp); + allocationInstruction2 = allocationInstruction; + } else { + type = ((NEWARRAY) allocationInstruction).getType(); + allocationInstruction2 = allocationInstruction; + } + short opcode = ((Instruction) allocationInstruction2).getOpcode(); + short value = 1; + switch (opcode) { + case 187: + this._out.println( + "il.append(_factory.createNew(\"" + ((ObjectType) type).getClassName() + "\"));"); + return; + case 197: + value = ((MULTIANEWARRAY) allocationInstruction).getDimensions(); + case 188: + case 189: + if (type instanceof ArrayType) { + type = ((ArrayType) type).getBasicType(); + } + this._out.println( + "il.append(_factory.createNewArray(" + + BCELifier.printType(type) + + ", (short) " + + value + + "));"); + return; + default: + throw new RuntimeException(("Oops: " + opcode)); + } + } + + @Override + public void visitFieldInstruction(FieldInstruction fieldInstruction) { + short opcode = fieldInstruction.getOpcode(); + String text2 = fieldInstruction.getText2(this._cp); + String fieldName = fieldInstruction.getFieldName(this._cp); + Type type2 = fieldInstruction.getType2(this._cp); + this._out.println( + "il.append(_factory.createFieldAccess(\"" + + text2 + + "\", \"" + + fieldName + + "\", " + + BCELifier.printType(type2) + + ", " + + "Constants." + + Constants.TEXTS8[opcode].toUpperCase(Locale.ENGLISH) + + "));"); + } + + @Override + public void visitConstantPushInstruction(ConstantPushInstruction constantPushInstruction) { + this.createConstant(constantPushInstruction.getValue()); + } + + @Override + public void visitReturnInstruction(ReturnInstruction returnInstruction) { + Type type = returnInstruction.getType(this._cp); + this._out.println("il.append(_factory.createReturn(" + BCELifier.printType(type) + "));"); + } + + @Override + public void visitLDC(LDC lDC) { + this.createConstant(lDC.getValue(this._cp)); + } + + public boolean visitInstruction(Instruction instruction) { + short opcode = instruction.getOpcode(); + if (InstructionConstants.INSTRUCTIONS[opcode] != null + && !(instruction instanceof ConstantPushInstruction) + && !(instruction instanceof ReturnInstruction)) { + this._out.println( + "il.append(InstructionConstants." + + instruction.getText().toUpperCase(Locale.ENGLISH) + + ");"); + return true; + } else { + return false; + } + } + + @Override + public void visitInvokeInstruction(InvokeInstruction invokeInstruction) { + short opcode = invokeInstruction.getOpcode(); + String text2 = invokeInstruction.getText2(this._cp); + String text4 = invokeInstruction.getText4(this._cp); + Type type2 = invokeInstruction.getType2(this._cp); + Type[] argumentTypes = invokeInstruction.getArgumentTypes(this._cp); + this._out.println( + "il.append(_factory.createInvoke(\"" + + text2 + + "\", \"" + + text4 + + "\", " + + BCELifier.printType(type2) + + ", " + + BCELifier.printArgumentTypes(argumentTypes) + + ", " + + "Constants." + + Constants.TEXTS8[opcode].toUpperCase(Locale.ENGLISH) + + "));"); + } + + @Override + public void visitLocalVariableInstruction(LocalVariableInstruction localVariableInstruction) { + short opcode = localVariableInstruction.getOpcode(); + Type type = localVariableInstruction.getType(this._cp); + if (opcode == 132) { + this._out.println( + "il.append(new IINC(" + + localVariableInstruction.getIndex() + + ", " + + ((IINC) localVariableInstruction).getIncrement() + + "));"); + } else { + String text = opcode < 54 ? "Load" : "Store"; + this._out.println( + "il.append(_factory.create" + + text + + "(" + + BCELifier.printType(type) + + ", " + + localVariableInstruction.getIndex() + + "));"); + } + } + + @Override + public void visitCHECKCAST(CHECKCAST cHECKCAST) { + Type type = cHECKCAST.getType(this._cp); + this._out.println("il.append(_factory.createCheckCast(" + BCELifier.printType(type) + "));"); + } + + @Override + public void visitLDC2_W(LDC2_W lDC2_W) { + this.createConstant(lDC2_W.getValue(this._cp)); + } + + public void createConstant(Object result) { + String text = result.toString(); + BCELFactory bCELFactory; + if (result instanceof String) { + text = '"' + Utility.createText(result.toString()) + '"'; + bCELFactory = this; + } else { + if (result instanceof Character) { + text = "(char)0x" + Integer.toHexString((Character) result); + } + bCELFactory = this; + } + bCELFactory._out.println("il.append(new PUSH(_cp, " + text + "));"); + } + + public void start() { + if (!this._mg.isEnabled15() && !this._mg.isEnabled14()) { + InstructionHandle instructionHandle; + for (InstructionHandle instructionHandle2 = + instructionHandle = this._mg.getInstructionList().getStart(); + instructionHandle2 != null; + instructionHandle2 = instructionHandle = instructionHandle.getInstructionHandle2()) { + Instruction instruction; + if ((instruction = instructionHandle.getInstruction()) instanceof BranchInstruction) { + this.branch_map.put(instruction, instructionHandle); + } + BCELFactory bCELFactory; + if (instructionHandle.hasTargeters()) { + if (instruction instanceof BranchInstruction) { + bCELFactory = this; + this._out.println(" InstructionHandle ih_" + instructionHandle.getPosition() + ";"); + } else { + bCELFactory = this; + this._out.print(" InstructionHandle ih_" + instructionHandle.getPosition() + " = "); + } + } else { + bCELFactory = this; + this._out.print(" "); + } + if (!bCELFactory.visitInstruction(instruction)) { + instruction.accept(this); + } + } + this.updateBranchTargets(); + this.updateExceptionHandlers(); + } + } + + public void updateBranchTargets() { + for (BranchInstruction branchInstruction : + ((Iterable) ((Iterable) this.branches))) { + BranchHandle branchHandle = (BranchHandle) this.branch_map.get(branchInstruction); + int position = branchHandle.getPosition(); + String text = "" + branchInstruction.getText() + "_" + position; + int position2 = branchHandle.getTarget().getPosition(); + this._out.println(" " + text + ".setTarget(ih_" + position2 + ");"); + if (branchInstruction instanceof Select) { + InstructionHandle[] targets = ((Select) branchInstruction).getTargets(); + int value; + for (int value2 = value = 0; value2 < targets.length; value2 = value) { + int position3 = targets[value].getPosition(); + PrintWriter printWriter = this._out; + StringBuilder stringBuilder = + new StringBuilder() + .insert(0, " ") + .append(text) + .append(".setTarget(") + .append(value) + .append(", ih_") + .append(position3); + value++; + printWriter.println(stringBuilder.append((String) ");").toString()); + } + } + } + } + + @Override + public void visitRET(RET rET) { + this._out.println("il.append(new RET(" + rET.getIndex() + ")));"); + } + + public void updateExceptionHandlers() { + CodeExceptionGen[] exceptionHandlers = this._mg.getExceptionHandlers(); + int value; + for (int value2 = value = 0; value2 < exceptionHandlers.length; value2 = value) { + CodeExceptionGen codeExceptionGen; + String text = + (codeExceptionGen = exceptionHandlers[value]).getCatchType() == null + ? "null" + : BCELifier.printType(codeExceptionGen.getCatchType()); + PrintWriter printWriter = this._out; + StringBuilder stringBuilder = + new StringBuilder() + .insert(0, " method.addExceptionHandler(ih_") + .append(codeExceptionGen.getInstructionHandle2().getPosition()) + .append(", ") + .append("ih_") + .append(codeExceptionGen.getInstructionHandle().getPosition()) + .append(", ") + .append("ih_") + .append(codeExceptionGen.getInstructionHandle3().getPosition()) + .append(", ") + .append(text); + value++; + printWriter.println(stringBuilder.append((String) ");").toString()); + } + } + + @Override + public void visitINSTANCEOF(INSTANCEOF nSTANCEOF) { + Type type = nSTANCEOF.getType(this._cp); + this._out.println( + "il.append(new INSTANCEOF(_cp.addClass(" + BCELifier.printType(type) + ")));"); + } + + @Override + public void visitArrayInstruction(ArrayInstruction arrayInstruction) { + short opcode = arrayInstruction.getOpcode(); + Type type = arrayInstruction.getType(this._cp); + String text = opcode < 79 ? "Load" : "Store"; + this._out.println( + "il.append(_factory.createArray" + text + "(" + BCELifier.printType(type) + "));"); + } + + @Override + public void visitBranchInstruction(BranchInstruction branchInstruction) { + BranchHandle branchHandle; + int position = + (branchHandle = (BranchHandle) this.branch_map.get(branchInstruction)).getPosition(); + String text = "" + branchInstruction.getText() + "_" + position; + BranchHandle branchHandle2; + if (branchInstruction instanceof Select) { + Select select = (Select) branchInstruction; + this.branches.add(branchInstruction); + StringBuffer stringBuffer = new StringBuffer("new int[] { "); + int[] match = select.getMatch(); + int value = 0; + for (int value2 = value; value2 < match.length; value2 = ++value) { + stringBuffer.append(match[value]); + if (value < match.length - 1) { + stringBuffer.append(", "); + } + } + stringBuffer.append(" }"); + this._out.print( + "Select " + + text + + " = new " + + branchInstruction.getText().toUpperCase(Locale.ENGLISH) + + "(" + + ((Object) stringBuffer) + + ", new InstructionHandle[] { "); + int value3 = 0; + for (int value4 = value3; value4 < match.length; value4 = ++value3) { + this._out.print("null"); + if (value3 < match.length - 1) { + this._out.print(", "); + } + } + this._out.println(" }, null);"); + branchHandle2 = branchHandle; + } else { + int position2 = branchHandle.getTarget().getPosition(); + String text2; + BCELFactory bCELFactory; + if (position > position2) { + text2 = "ih_" + position2; + bCELFactory = this; + } else { + bCELFactory = this; + this.branches.add(branchInstruction); + text2 = "null"; + } + bCELFactory._out.println( + " BranchInstruction " + + text + + " = _factory.createBranchInstruction(" + + "Constants." + + branchInstruction.getText().toUpperCase(Locale.ENGLISH) + + ", " + + text2 + + ");"); + branchHandle2 = branchHandle; + } + if (branchHandle2.hasTargeters()) { + this._out.println(" ih_" + position + " = il.append(" + text + ");"); + } else { + this._out.println(" il.append(" + text + ");"); + } + } +} diff --git a/src/main/java/com/allatori/lib/bcel/util/BCELifier.java b/src/main/java/com/allatori/lib/bcel/util/BCELifier.java new file mode 100644 index 0000000..365fcf3 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/util/BCELifier.java @@ -0,0 +1,288 @@ +package com.allatori.lib.bcel.util; + +import com.allatori.lib.bcel.Constants; +import com.allatori.lib.bcel.classfile.ClassParser; +import com.allatori.lib.bcel.classfile.ConstantValue; +import com.allatori.lib.bcel.classfile.EmptyVisitor; +import com.allatori.lib.bcel.classfile.Field; +import com.allatori.lib.bcel.classfile.JavaClass; +import com.allatori.lib.bcel.classfile.Method; +import com.allatori.lib.bcel.classfile.Utility; +import com.allatori.lib.bcel.generic.ArrayType; +import com.allatori.lib.bcel.generic.ConstantPoolGen; +import com.allatori.lib.bcel.generic.MethodGen; +import com.allatori.lib.bcel.generic.Type; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.util.Locale; + +public class BCELifier extends EmptyVisitor { + + public static final int FLAG_FOR_UNKNOWN = -1; + + public PrintWriter _out; + + public ConstantPoolGen _cp; + + public static final int FLAG_FOR_CLASS = 0; + + public JavaClass _clazz; + + public static final int FLAG_FOR_METHOD = 1; + + @Override + public void visitField(Field field) { + this._out.println(); + this._out.println( + " field = new FieldGen(" + + printFlags(field.getAccess_flags2()) + + ", " + + printType(field.getText2()) + + ", \"" + + field.getText() + + "\", _cp);"); + ConstantValue constantValue; + if ((constantValue = field.getConstantValue()) != null) { + String text = constantValue.toString(); + this._out.println(" field.setInitValue(" + text + ")"); + } + this._out.println(" _cg.addField(field.getField());"); + } + + @Override + public void visitMethod(Method method) { + MethodGen methodGen; + MethodGen methodGen2 = methodGen = new MethodGen(method, this._clazz.getText2(), this._cp); + Type returnType = methodGen2.getReturnType(); + Type[] argumentTypes = methodGen2.getArgumentTypes(); + this._out.println(" InstructionList il = new InstructionList();"); + this._out.println( + " MethodGen method = new MethodGen(" + + printFlags(method.getAccess_flags2(), 1) + + ", " + + printType(returnType) + + ", " + + printArgumentTypes(argumentTypes) + + ", " + + "new String[] { " + + Utility.printArray(methodGen.getArgumentNames(), false, true) + + " }, \"" + + method.getText() + + "\", \"" + + this._clazz.getText2() + + "\", il, _cp);"); + this._out.println(); + new BCELFactory(methodGen, this._out).start(); + this._out.println(" method.setMaxStack();"); + this._out.println(" method.setMaxLocals();"); + this._out.println(" _cg.addMethod(method.getMethod());"); + this._out.println(" il.dispose();"); + } + + public BCELifier(JavaClass javaClass, OutputStream outputStream) { + super(); + this._clazz = javaClass; + this._out = new PrintWriter(outputStream); + this._cp = new ConstantPoolGen(this._clazz.getConstantPool()); + } + + public static String printType(Type type) { + return printType(type.getSignature()); + } + + public void start() { + this.visitJavaClass(this._clazz); + this._out.flush(); + } + + public static String printArgumentTypes(Type[] types) { + if (types.length == 0) { + return "Type.NO_ARGS"; + } + StringBuffer stringBuffer = new StringBuffer(); + int value; + for (int value2 = value = 0; value2 < types.length; value2 = ++value) { + stringBuffer.append(printType(types[value])); + if (value < types.length - 1) { + stringBuffer.append(", "); + } + } + return "new Type[] { " + stringBuffer.toString() + " }"; + } + + @Override + public void visitJavaClass(JavaClass javaClass) { + String text2 = javaClass.getText2(); + String text5 = javaClass.getText5(); + String text4 = javaClass.getText4(); + String text = Utility.printArray(javaClass.getInterfaceNames(), false, true); + if (!"".equals(text4)) { + text2 = text2.substring(text4.length() + 1); + this._out.println("package " + text4 + ";"); + this._out.println(); + } + this._out.println("import org.apache.bcel.generic.*;"); + this._out.println("import org.apache.bcel.classfile.*;"); + this._out.println("import org.apache.bcel.*;"); + this._out.println("import java.io.*;"); + this._out.println(); + this._out.println("public class " + text2 + "Creator implements Constants {"); + this._out.println(" private InstructionFactory _factory;"); + this._out.println(" private ConstantPoolGen _cp;"); + this._out.println(" private ClassGen _cg;"); + this._out.println(); + this._out.println(" public " + text2 + "Creator() {"); + this._out.println( + " _cg = new ClassGen(\"" + + ("".equals(text4) + ? text2 + : new StringBuilder().insert(0, text4).append(".").append(text2).toString()) + + "\", \"" + + text5 + + "\", " + + "\"" + + javaClass.getText() + + "\", " + + printFlags(javaClass.getAccess_flags2(), 0) + + ", " + + "new String[] { " + + text + + " });"); + this._out.println(); + this._out.println(" _cp = _cg.getConstantPool();"); + this._out.println(" _factory = new InstructionFactory(_cg, _cp);"); + this._out.println(" }"); + this._out.println(); + this.printCreate(); + Field[] fields; + if ((fields = javaClass.getFields()).length > 0) { + int value = 0; + this._out.println(" private void createFields() {"); + this._out.println(" FieldGen field;"); + for (int index = 0; value < fields.length; value = index) { + int value2 = index; + Field[] fields2 = fields; + index++; + fields2[value2].accept(this); + } + this._out.println(" }"); + this._out.println(); + } + Method[] methods = javaClass.getMethods(); + int value3; + for (int value4 = value3 = 0; value4 < methods.length; value4 = value3) { + this._out.println(" private void createMethod_" + value3 + "() {"); + methods[value3].accept(this); + PrintWriter printWriter = this._out; + value3++; + printWriter.println((String) " }"); + this._out.println(); + } + this.printMain(); + this._out.println("}"); + } + + public static void main(String[] texts) throws Exception { + JavaClass javaClass; + String text; + if ((javaClass = com.allatori.lib.bcel.Repository.lookupClass(text = texts[0])) == null) { + javaClass = new ClassParser(text).parse(); + } + new BCELifier(javaClass, System.out).start(); + } + + public static String printFlags(int value) { + return printFlags(value, -1); + } + + public void printCreate() { + this._out.println(" public void create(OutputStream out) throws IOException {"); + if (this._clazz.getFields().length > 0) { + this._out.println(" createFields();"); + } + Method[] methods = this._clazz.getMethods(); + int value; + for (int value2 = value = 0; value2 < methods.length; value2 = value) { + PrintWriter printWriter = this._out; + StringBuilder stringBuilder = + new StringBuilder().insert(0, " createMethod_").append(value); + value++; + printWriter.println(stringBuilder.append((String) "();").toString()); + } + this._out.println(" _cg.getJavaClass().dump(out);"); + this._out.println(" }"); + this._out.println(); + } + + public static String printType(String text) { + byte value; + Type type; + if ((value = (type = Type.getType(text)).getType()) <= 12) { + return "Type." + Constants.TEXTS[value].toUpperCase(Locale.ENGLISH); + } else if (type.toString().equals("java.lang.String")) { + return "Type.STRING"; + } else if (type.toString().equals("java.lang.Object")) { + return "Type.OBJECT"; + } else if (type.toString().equals("java.lang.StringBuffer")) { + return "Type.STRINGBUFFER"; + } else if (type instanceof ArrayType) { + ArrayType arrayType = (ArrayType) type; + return "new ArrayType(" + + printType(arrayType.getBasicType()) + + ", " + + arrayType.getDimensions() + + ")"; + } else { + return "new ObjectType(\"" + Utility.signatureToString(text, false) + "\")"; + } + } + + public void printMain() { + String text2 = this._clazz.getText2(); + this._out.println(" public static void main(String[] args) throws Exception {"); + this._out.println(" " + text2 + "Creator creator = new " + text2 + "Creator();"); + this._out.println(" creator.create(new FileOutputStream(\"" + text2 + ".class\"));"); + this._out.println(" }"); + } + + public static String printFlags(int value, int value2) { + if (value == 0) { + return "0"; + } + StringBuffer stringBuffer = new StringBuffer(); + int value3 = 0; + int value4; + for (int value5 = value4 = 1; value5 <= 16384; value5 = value4) { + label37: + { + if ((value & value4) != 0) { + if (value4 == 32 && value2 == 0) { + value5 = value4; + stringBuffer.append("ACC_SUPER | "); + break label37; + } + if (value4 == 64 && value2 == 1) { + value5 = value4; + stringBuffer.append("ACC_BRIDGE | "); + break label37; + } + if (value4 == 128 && value2 == 1) { + value5 = value4; + stringBuffer.append("ACC_VARARGS | "); + break label37; + } + stringBuffer + .append("ACC_") + .append(Constants.TEXTS9[value3].toUpperCase(Locale.ENGLISH)) + .append(" | "); + } + value5 = value4; + } + int value6 = value5; + value3++; + value4 = value6 << (byte) 1; + } + String text = stringBuffer.toString(); + return text.substring(0, text.length() - 3); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/util/ByteSequence$ByteArrayStream.java b/src/main/java/com/allatori/lib/bcel/util/ByteSequence$ByteArrayStream.java new file mode 100644 index 0000000..470b128 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/util/ByteSequence$ByteArrayStream.java @@ -0,0 +1,20 @@ +package com.allatori.lib.bcel.util; + +import java.io.ByteArrayInputStream; + +public final class ByteSequence$ByteArrayStream extends ByteArrayInputStream { + + public final int getPosition() { + return this.pos; + } + + public ByteSequence$ByteArrayStream(byte[] values) { + super(values); + } + + public final void unreadByte() { + if (this.pos > 0) { + this.pos--; + } + } +} diff --git a/src/main/java/com/allatori/lib/bcel/util/ByteSequence.java b/src/main/java/com/allatori/lib/bcel/util/ByteSequence.java new file mode 100644 index 0000000..e06f456 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/util/ByteSequence.java @@ -0,0 +1,21 @@ +package com.allatori.lib.bcel.util; + +import java.io.DataInputStream; + +public final class ByteSequence extends DataInputStream { + + public ByteSequence$ByteArrayStream byte_stream; + + public final int getIndex() { + return this.byte_stream.getPosition(); + } + + public ByteSequence(byte[] values) { + super(new ByteSequence$ByteArrayStream(values)); + this.byte_stream = (ByteSequence$ByteArrayStream) this.in; + } + + public final void unreadByte() { + this.byte_stream.unreadByte(); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/util/Class2HTML.java b/src/main/java/com/allatori/lib/bcel/util/Class2HTML.java new file mode 100644 index 0000000..826d975 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/util/Class2HTML.java @@ -0,0 +1,197 @@ +package com.allatori.lib.bcel.util; + +import com.allatori.lib.bcel.Constants; +import com.allatori.lib.bcel.classfile.Attribute; +import com.allatori.lib.bcel.classfile.ClassParser; +import com.allatori.lib.bcel.classfile.ConstantPool; +import com.allatori.lib.bcel.classfile.JavaClass; +import com.allatori.lib.bcel.classfile.Method; +import com.allatori.lib.bcel.classfile.Utility; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.io.PrintWriter; + +public class Class2HTML implements Constants { + + public static String text; + + public String dir; + + public static ConstantPool constant_pool; + + public static String text2; + + public JavaClass java_class; + + public static final String createText(String text) { + String text3 = Utility.getText(text); + String text4 = Utility.compactClassName(text3, text2 + ".", true); + int value = text.indexOf(91); + String text5 = text; + if (value > -1) { + text5 = text.substring(0, value); + } + return !text5.equals("int") + && !text5.equals("short") + && !text5.equals("boolean") + && !text5.equals("void") + && !text5.equals("char") + && !text5.equals("byte") + && !text5.equals("long") + && !text5.equals("double") + && !text5.equals("float") + ? ("" + text4 + "") + : ("" + text + ""); + } + + public void writeMainHTML(AttributeHTML attributeHTML) throws IOException { + PrintWriter printWriter = + new PrintWriter(new FileOutputStream(("" + this.dir + text + ".html"))); + Attribute[] attributes = this.java_class.getAttributes(); + int value = 0; + printWriter.println( + "\nDocumentation for " + + text + + "" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + ""); + printWriter.close(); + for (int index = 0; value < attributes.length; value = index) { + Attribute attribute = attributes[index]; + StringBuilder stringBuilder = new StringBuilder().insert(0, "class"); + int value2 = index; + index++; + attributeHTML.writeAttribute(attribute, stringBuilder.append(value2).toString()); + } + } + + public static String referenceClass(int value) { + String text3 = Utility.getText(constant_pool.createText(value, (byte) 7)); + String text4 = Utility.compactClassName(text3, text2 + ".", true); + return "" + text4 + ""; + } + + public static String createText2(String text) { + StringBuffer stringBuffer = new StringBuffer(); + try { + for (int index = 0; index < text.length(); index++) { + char value; + switch (value = text.charAt(index)) { + case '\n': + stringBuffer.append("\\n"); + break; + case '\r': + stringBuffer.append("\\r"); + break; + case '<': + stringBuffer.append("<"); + break; + case '>': + stringBuffer.append(">"); + break; + default: + stringBuffer.append(value); + } + } + } catch (StringIndexOutOfBoundsException stringIndexOutOfBoundsException) { + } + return stringBuffer.toString(); + } + + public Class2HTML(JavaClass javaClass, String dir) throws IOException { + Method[] methods = javaClass.getMethods(); + this.java_class = javaClass; + this.dir = dir; + text = javaClass.getText2(); + constant_pool = javaClass.getConstantPool(); + int value; + if ((value = text.lastIndexOf(46)) > -1) { + text2 = text.substring(0, value); + } else { + text2 = ""; + } + ConstantHTML constantHTML = new ConstantHTML(dir, text, text2, methods, constant_pool); + AttributeHTML attributeHTML = new AttributeHTML(dir, text, constant_pool, constantHTML); + new MethodHTML(dir, text, methods, javaClass.getFields(), constantHTML, attributeHTML); + this.writeMainHTML(attributeHTML); + new CodeHTML(dir, text, methods, constant_pool, constantHTML); + attributeHTML.close(); + } + + public static void main(String[] texts) throws IOException { + String[] texts2 = new String[texts.length]; + int value = 0; + String text = null; + char value2 = System.getProperty("file.separator").toCharArray()[0]; + String text2 = "." + value2; + try { + int value3; + for (int value4 = value3 = 0; value4 < texts.length; value4 = ++value3) { + if (texts[value3].charAt(0) == '-') { + if (texts[value3].equals("-d")) { + text2 = texts[++value3]; + if (!text2.endsWith("" + value2)) { + text2 = "" + text2 + value2; + } + new File(text2).mkdirs(); + } else if (texts[value3].equals("-zip")) { + text = texts[++value3]; + } else { + System.out.println("Unknown option " + texts[value3]); + } + } else { + int value5 = value3; + int value6 = value; + value++; + texts2[value6] = texts[value5]; + } + } + if (value == 0) { + System.err.println("Class2HTML: No input files specified."); + return; + } + int value7 = 0; + while (value7 < value) { + System.out.print("Processing " + texts2[value7] + "..."); + ClassParser classParser; + if (text == null) { + classParser = new ClassParser(texts2[value7]); + } else { + classParser = new ClassParser(text, texts2[value7]); + } + JavaClass javaClass = classParser.parse(); + new Class2HTML(javaClass, text2); + PrintStream printStream = System.out; + value7++; + printStream.println("Done."); + } + } catch (Exception exception) { + System.out.println(exception); + exception.printStackTrace(System.out); + } + } +} diff --git a/src/main/java/com/allatori/lib/bcel/util/ClassLoader.java b/src/main/java/com/allatori/lib/bcel/util/ClassLoader.java new file mode 100644 index 0000000..a04d0aa --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/util/ClassLoader.java @@ -0,0 +1,120 @@ +package com.allatori.lib.bcel.util; + +import com.allatori.lib.bcel.classfile.ClassParser; +import com.allatori.lib.bcel.classfile.ConstantClass; +import com.allatori.lib.bcel.classfile.ConstantPool; +import com.allatori.lib.bcel.classfile.ConstantUtf8; +import com.allatori.lib.bcel.classfile.JavaClass; +import com.allatori.lib.bcel.classfile.Utility; +import java.io.ByteArrayInputStream; +import java.util.Hashtable; + +public class ClassLoader extends java.lang.ClassLoader { + + public static final String[] DEFAULT_IGNORED_PACKAGES = new String[] {"java.", "javax.", "sun."}; + + public String[] ignored_packages; + + public Hashtable classes; + + public Repository repository; + + public ClassLoader(java.lang.ClassLoader classLoader) { + super(classLoader); + this.classes = new Hashtable(); + this.repository = SyntheticRepository.getInstance(); + this.ignored_packages = DEFAULT_IGNORED_PACKAGES; + this.repository = new ClassLoaderRepository(classLoader); + } + + @Override + public Class loadClass(String text, boolean matches) throws ClassNotFoundException { + boolean matches2; + Class classValue; + Class classValue2; + if ((classValue2 = (Class) this.classes.get(text)) == null) { + int value; + int value2 = value = 0; + while (true) { + if (value2 >= this.ignored_packages.length) { + classValue = classValue2; + break; + } + if (text.startsWith(this.ignored_packages[value])) { + classValue = classValue2 = this.getParent().loadClass(text); + break; + } + value2 = ++value; + } + label33: + { + if (classValue == null) { + JavaClass javaClass; + JavaClass javaClass2; + if (text.indexOf("$$BCEL$$") >= 0) { + javaClass2 = javaClass = this.createClass(text); + } else { + JavaClass javaClass3; + if ((javaClass3 = this.repository.getJavaClass2(text)) == null) { + throw new ClassNotFoundException(text); + } + javaClass2 = javaClass = this.modifyClass(javaClass3); + } + if (javaClass2 != null) { + byte[] bytes = javaClass.getBytes(); + classValue2 = this.defineClass(text, bytes, 0, bytes.length); + matches2 = matches; + break label33; + } + classValue2 = Class.forName(text); + } + matches2 = matches; + } + if (matches2) { + this.resolveClass(classValue2); + } + } + this.classes.put(text, classValue2); + return classValue2; + } + + public JavaClass createClass(String text) { + String text2 = text.substring(text.indexOf("$$BCEL$$") + 8); + JavaClass javaClass; + try { + byte[] values = Utility.decode(text2, true); + javaClass = new ClassParser(new ByteArrayInputStream(values), "foo").parse(); + } catch (Throwable throwable) { + throwable.printStackTrace(); + return null; + } + ConstantPool constantPool; + ConstantClass constantClass = + (ConstantClass) + (constantPool = javaClass.getConstantPool()) + .getConstant(javaClass.getCount(), (byte) 7); + ((ConstantUtf8) constantPool.getConstant(constantClass.getNameIndex(), (byte) 1)) + .setBytes(text.replace('.', '/')); + return javaClass; + } + + public ClassLoader() { + this(DEFAULT_IGNORED_PACKAGES); + } + + public ClassLoader(String[] texts) { + super(); + this.classes = new Hashtable(); + this.repository = SyntheticRepository.getInstance(); + this.ignored_packages = texts; + } + + public JavaClass modifyClass(JavaClass javaClass) { + return javaClass; + } + + public ClassLoader(java.lang.ClassLoader classLoader, String[] texts) { + this(texts); + this.repository = new ClassLoaderRepository(classLoader); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/util/ClassLoaderRepository.java b/src/main/java/com/allatori/lib/bcel/util/ClassLoaderRepository.java new file mode 100644 index 0000000..8767ed0 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/util/ClassLoaderRepository.java @@ -0,0 +1,72 @@ +package com.allatori.lib.bcel.util; + +import com.allatori.lib.bcel.classfile.ClassParser; +import com.allatori.lib.bcel.classfile.JavaClass; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; + +public class ClassLoaderRepository implements Repository { + + public Map loadedClasses; + + public java.lang.ClassLoader loader; + + @Override + public void processJavaClass2(JavaClass javaClass) { + this.loadedClasses.remove(javaClass.getText2()); + } + + @Override + public void processJavaClass(JavaClass javaClass) { + this.loadedClasses.put(javaClass.getText2(), javaClass); + javaClass.setRepository(this); + } + + public ClassLoaderRepository(java.lang.ClassLoader classLoader) { + super(); + this.loadedClasses = new HashMap(); + this.loader = classLoader; + } + + @Override + public ClassPath getClassPath() { + return null; + } + + @Override + public JavaClass getJavaClass(String text) { + return this.loadedClasses.containsKey(text) ? (JavaClass) this.loadedClasses.get(text) : null; + } + + @Override + public JavaClass loadClass(Class classValue) throws ClassNotFoundException { + return this.getJavaClass2(classValue.getName()); + } + + @Override + public JavaClass getJavaClass2(String text) throws ClassNotFoundException { + String text2 = text.replace('.', '/'); + JavaClass javaClass; + if ((javaClass = this.getJavaClass(text)) != null) { + return javaClass; + } + try { + InputStream inputStream; + if ((inputStream = this.loader.getResourceAsStream("" + text2 + ".class")) == null) { + throw new ClassNotFoundException(("" + text + " not found.")); + } + JavaClass javaClass2 = new ClassParser(inputStream, text).parse(); + this.processJavaClass(javaClass2); + return javaClass2; + } catch (IOException oException) { + throw new ClassNotFoundException(oException.toString()); + } + } + + @Override + public void clear() { + this.loadedClasses.clear(); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/util/ClassPath$1.java b/src/main/java/com/allatori/lib/bcel/util/ClassPath$1.java new file mode 100644 index 0000000..d8c9726 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/util/ClassPath$1.java @@ -0,0 +1,14 @@ +package com.allatori.lib.bcel.util; + +import java.io.File; +import java.io.FilenameFilter; +import java.util.Locale; + +public class ClassPath$1 implements FilenameFilter { + + @Override + public boolean accept(File file, String text) { + String text2; + return (text2 = text.toLowerCase(Locale.ENGLISH)).endsWith(".zip") || text2.endsWith(".jar"); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/util/ClassPath$ClassFile.java b/src/main/java/com/allatori/lib/bcel/util/ClassPath$ClassFile.java new file mode 100644 index 0000000..da4733d --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/util/ClassPath$ClassFile.java @@ -0,0 +1,17 @@ +package com.allatori.lib.bcel.util; + +import java.io.IOException; +import java.io.InputStream; + +public interface ClassPath$ClassFile { + + InputStream getInputStream() throws IOException; + + String getText(); + + String getText2(); + + long calculateSeed(); + + long calculateSeed2(); +} diff --git a/src/main/java/com/allatori/lib/bcel/util/ClassPath$Dir$1.java b/src/main/java/com/allatori/lib/bcel/util/ClassPath$Dir$1.java new file mode 100644 index 0000000..d25f876 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/util/ClassPath$Dir$1.java @@ -0,0 +1,49 @@ +package com.allatori.lib.bcel.util; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; + +public class ClassPath$Dir$1 implements ClassPath$ClassFile { + + public final File val$file; + + public final ClassPath$Dir this$0; + + @Override + public String getText() { + return ClassPath$Dir.access$100(this.this$0); + } + + public ClassPath$Dir$1(ClassPath$Dir classPath$Dir, File file) throws FileNotFoundException { + super(); + this.this$0 = classPath$Dir; + this.val$file = file; + } + + @Override + public String getText2() { + try { + return this.val$file.getCanonicalPath(); + } catch (IOException oException) { + return null; + } + } + + @Override + public long calculateSeed2() { + return this.val$file.length(); + } + + @Override + public InputStream getInputStream() throws IOException { + return new FileInputStream(this.val$file); + } + + @Override + public long calculateSeed() { + return this.val$file.lastModified(); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/util/ClassPath$Dir.java b/src/main/java/com/allatori/lib/bcel/util/ClassPath$Dir.java new file mode 100644 index 0000000..89d818e --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/util/ClassPath$Dir.java @@ -0,0 +1,59 @@ +package com.allatori.lib.bcel.util; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; + +public class ClassPath$Dir extends ClassPath$PathEntry { + + public String dir; + + @Override + public URL getResource(String text) { + File file = + new File(("" + this.dir + File.separatorChar + text.replace('/', File.separatorChar))); + try { + return file.exists() ? file.toURL() : null; + } catch (MalformedURLException malformedURLException) { + return null; + } + } + + @Override + public ClassPath$ClassFile getClassFile(String text, String text2) throws IOException { + File file; + return (file = + new File( + ("" + + this.dir + + File.separatorChar + + text.replace('.', File.separatorChar) + + text2))) + .exists() + ? new ClassPath$Dir$1(this, file) + : null; + } + + @Override + public InputStream getResourceAsStream(String text) { + File file = + new File(("" + this.dir + File.separatorChar + text.replace('/', File.separatorChar))); + try { + return file.exists() ? new FileInputStream(file) : null; + } catch (IOException oException) { + return null; + } + } + + public static String access$100(ClassPath$Dir classPath$Dir) { + return classPath$Dir.dir; + } + + public ClassPath$Dir(String dir) { + super(null); + this.dir = dir; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/util/ClassPath$PathEntry.java b/src/main/java/com/allatori/lib/bcel/util/ClassPath$PathEntry.java new file mode 100644 index 0000000..ae1d949 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/util/ClassPath$PathEntry.java @@ -0,0 +1,21 @@ +package com.allatori.lib.bcel.util; + +import java.io.IOException; +import java.io.InputStream; +import java.io.Serializable; +import java.net.URL; + +public abstract class ClassPath$PathEntry implements Serializable { + + public ClassPath$PathEntry() {} + + public ClassPath$PathEntry(ClassPath$1 classPath$1) { + this(); + } + + public abstract InputStream getResourceAsStream(String text); + + public abstract ClassPath$ClassFile getClassFile(String text, String text2) throws IOException; + + public abstract URL getResource(String text); +} diff --git a/src/main/java/com/allatori/lib/bcel/util/ClassPath$Zip$1.java b/src/main/java/com/allatori/lib/bcel/util/ClassPath$Zip$1.java new file mode 100644 index 0000000..cc65fef --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/util/ClassPath$Zip$1.java @@ -0,0 +1,43 @@ +package com.allatori.lib.bcel.util; + +import java.io.IOException; +import java.io.InputStream; +import java.util.zip.ZipEntry; + +public class ClassPath$Zip$1 implements ClassPath$ClassFile { + + public final ZipEntry val$entry; + + public final ClassPath$Zip this$0; + + public ClassPath$Zip$1(ClassPath$Zip classPath$Zip, ZipEntry zipEntry) throws IOException { + super(); + this.this$0 = classPath$Zip; + this.val$entry = zipEntry; + } + + @Override + public String getText() { + return ClassPath$Zip.access$200(this.this$0).getName(); + } + + @Override + public String getText2() { + return this.val$entry.toString(); + } + + @Override + public long calculateSeed2() { + return this.val$entry.getSize(); + } + + @Override + public InputStream getInputStream() throws IOException { + return ClassPath$Zip.access$200(this.this$0).getInputStream(this.val$entry); + } + + @Override + public long calculateSeed() { + return this.val$entry.getTime(); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/util/ClassPath$Zip.java b/src/main/java/com/allatori/lib/bcel/util/ClassPath$Zip.java new file mode 100644 index 0000000..be16b03 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/util/ClassPath$Zip.java @@ -0,0 +1,50 @@ +package com.allatori.lib.bcel.util; + +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +public class ClassPath$Zip extends ClassPath$PathEntry { + + public ZipFile zip; + + public ClassPath$Zip(ZipFile zipFile) { + super(null); + this.zip = zipFile; + } + + @Override + public InputStream getResourceAsStream(String text) { + ZipEntry entry = this.zip.getEntry(text); + try { + return entry != null ? this.zip.getInputStream(entry) : null; + } catch (IOException oException) { + return null; + } + } + + @Override + public URL getResource(String text) { + ZipEntry entry = this.zip.getEntry(text); + try { + return entry != null ? new URL(("jar:file:" + this.zip.getName() + "!/" + text)) : null; + } catch (MalformedURLException malformedURLException) { + return null; + } + } + + @Override + public ClassPath$ClassFile getClassFile(String text, String text2) throws IOException { + ZipEntry zipEntry; + return (zipEntry = this.zip.getEntry("" + text.replace('.', '/') + text2)) == null + ? null + : new ClassPath$Zip$1(this, zipEntry); + } + + public static ZipFile access$200(ClassPath$Zip classPath$Zip) { + return classPath$Zip.zip; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/util/ClassPath.java b/src/main/java/com/allatori/lib/bcel/util/ClassPath.java new file mode 100644 index 0000000..a41a4f3 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/util/ClassPath.java @@ -0,0 +1,215 @@ +package com.allatori.lib.bcel.util; + +import java.io.DataInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.Serializable; +import java.net.URL; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.StringTokenizer; +import java.util.zip.ZipFile; + +public class ClassPath implements Serializable { + + public ClassPath$PathEntry[] paths; + + public static final ClassPath SYSTEM_CLASS_PATH = new ClassPath(); + + public String class_path; + + @Override + public int hashCode() { + return this.class_path.hashCode(); + } + + public ClassPath(String class_path) { + this.class_path = class_path; + ArrayList values = new ArrayList(); + StringTokenizer stringTokenizer = + new StringTokenizer(class_path, System.getProperty("path.separator")); + while (stringTokenizer.hasMoreTokens()) { + String text2; + if (!(text2 = stringTokenizer.nextToken()).equals("")) { + File file = new File(text2); + try { + if (file.exists()) { + if (file.isDirectory()) { + values.add(new ClassPath$Dir(text2)); + } else { + values.add(new ClassPath$Zip(new ZipFile(file))); + } + } + } catch (IOException oException) { + System.err.println("CLASSPATH component " + file + ": " + oException); + } + } + } + this.paths = new ClassPath$PathEntry[values.size()]; + values.toArray(this.paths); + } + + public static final void getPathComponents(String text, List values) { + if (text != null) { + StringTokenizer stringTokenizer = new StringTokenizer(text, File.pathSeparator); + while (stringTokenizer.hasMoreTokens()) { + String text2 = stringTokenizer.nextToken(); + if (new File(text2).exists()) { + values.add(text2); + } + } + } + } + + public byte[] getBytes(String text) throws IOException { + return this.getBytes(text, ".class"); + } + + public InputStream getInputStream(String text, String text2) throws IOException { + InputStream inputStream = null; + try { + inputStream = this.getClass().getClassLoader().getResourceAsStream("" + text + text2); + } catch (Exception exception) { + return inputStream != null ? inputStream : this.getClassFile(text, text2).getInputStream(); + } + return inputStream != null ? inputStream : this.getClassFile(text, text2).getInputStream(); + } + + public byte[] getBytes(String text, String text2) throws IOException { + DataInputStream dataInputStream = null; + boolean matches = false; + byte[] values; + try { + matches = true; + InputStream inputStream; + if ((inputStream = this.getInputStream(text, text2)) == null) { + throw new IOException(("Couldn't find: " + text + text2)); + } + dataInputStream = new DataInputStream(inputStream); + byte[] values2 = new byte[inputStream.available()]; + dataInputStream.readFully(values2); + values = values2; + matches = false; + } finally { + if (matches) { + if (dataInputStream != null) { + dataInputStream.close(); + } + } + } + dataInputStream.close(); + return values; + } + + public InputStream getInputStream(String text) throws IOException { + int value; + for (int value2 = value = 0; value2 < this.paths.length; value2 = ++value) { + InputStream inputStream; + if ((inputStream = this.paths[value].getResourceAsStream(text)) != null) { + return inputStream; + } + } + return null; + } + + public InputStream getInputStream2(String text) throws IOException { + return this.getInputStream(text.replace('.', '/'), ".class"); + } + + public static final String getClassPath() { + String property = System.getProperty("java.class.path"); + String property2 = System.getProperty("sun.boot.class.path"); + String property3 = System.getProperty("java.ext.dirs"); + ArrayList values = new ArrayList(); + getPathComponents(property, values); + getPathComponents(property2, values); + ArrayList values2 = new ArrayList(); + getPathComponents(property3, values2); + Iterator iterator2 = values2.iterator(); + while (iterator2.hasNext()) { + File file = new File((String) iterator2.next()); + int value; + String[] texts; + if ((texts = file.list(new ClassPath$1())) != null) { + for (int value2 = value = 0; value2 < texts.length; value2 = value) { + StringBuilder stringBuilder = + new StringBuilder().insert(0, file.getPath()).append(File.separatorChar); + String text = texts[value]; + value++; + values.add(stringBuilder.append(text).toString()); + } + } + } + StringBuffer stringBuffer = new StringBuffer(); + Iterator iterator3 = values.iterator(); + label23: + while (true) { + Iterator iterator4 = iterator3; + while (iterator4.hasNext()) { + stringBuffer.append((String) iterator3.next()); + if (!iterator3.hasNext()) { + continue label23; + } + iterator4 = iterator3; + stringBuffer.append(File.pathSeparatorChar); + } + return stringBuffer.toString().intern(); + } + } + + public String getPath(String text) throws IOException { + int value = text.lastIndexOf(46); + String text2 = ""; + if (value > 0) { + text2 = text.substring(value); + text = text.substring(0, value); + } + return this.getPath(text, text2); + } + + public ClassPath$ClassFile getClassFile(String text) throws IOException { + return this.getClassFile(text, ".class"); + } + + public ClassPath$ClassFile getClassFile(String text, String text2) throws IOException { + int value; + for (int value2 = value = 0; value2 < this.paths.length; value2 = ++value) { + ClassPath$ClassFile classPath$ClassFile; + if ((classPath$ClassFile = this.paths[value].getClassFile(text, text2)) != null) { + return classPath$ClassFile; + } + } + throw new IOException(("Couldn't find: " + text + text2)); + } + + @Override + public boolean equals(Object result) { + return result instanceof ClassPath + ? this.class_path.equals(((ClassPath) result).class_path) + : false; + } + + /** + * @deprecated + */ + public ClassPath() { + this(getClassPath()); + } + + public URL getURL(String text) { + int value; + for (int value2 = value = 0; value2 < this.paths.length; value2 = ++value) { + URL uRL; + if ((uRL = this.paths[value].getResource(text)) != null) { + return uRL; + } + } + return null; + } + + public String getPath(String text, String text2) throws IOException { + return this.getClassFile(text, text2).getText2(); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/util/ClassQueue.java b/src/main/java/com/allatori/lib/bcel/util/ClassQueue.java new file mode 100644 index 0000000..d826978 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/util/ClassQueue.java @@ -0,0 +1,22 @@ +package com.allatori.lib.bcel.util; + +import com.allatori.lib.bcel.classfile.JavaClass; +import java.io.Serializable; +import java.util.LinkedList; + +public class ClassQueue implements Serializable { + + public LinkedList vec = new LinkedList(); + + public boolean empty() { + return this.vec.isEmpty(); + } + + public JavaClass dequeue() { + return (JavaClass) this.vec.removeFirst(); + } + + public void enqueue(JavaClass javaClass) { + this.vec.addLast(javaClass); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/util/ClassSet.java b/src/main/java/com/allatori/lib/bcel/util/ClassSet.java new file mode 100644 index 0000000..30aa685 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/util/ClassSet.java @@ -0,0 +1,40 @@ +package com.allatori.lib.bcel.util; + +import com.allatori.lib.bcel.classfile.JavaClass; +import java.io.Serializable; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +public class ClassSet implements Serializable { + + public Map _map = new HashMap(); + + public JavaClass[] toArray() { + Collection values2; + JavaClass[] javaClasss = new JavaClass[(values2 = this._map.values()).size()]; + values2.toArray(javaClasss); + return javaClasss; + } + + public boolean empty() { + return this._map.isEmpty(); + } + + public String[] getClassNames() { + return (String[]) this._map.keySet().toArray(new String[this._map.keySet().size()]); + } + + public boolean add(JavaClass javaClass) { + byte value = 0; + if (!this._map.containsKey(javaClass.getText2())) { + value = 1; + this._map.put(javaClass.getText2(), javaClass); + } + return value != 0; + } + + public void remove(JavaClass javaClass) { + this._map.remove(javaClass.getText2()); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/util/ClassStack.java b/src/main/java/com/allatori/lib/bcel/util/ClassStack.java new file mode 100644 index 0000000..6445898 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/util/ClassStack.java @@ -0,0 +1,26 @@ +package com.allatori.lib.bcel.util; + +import com.allatori.lib.bcel.classfile.JavaClass; +import java.io.Serializable; +import java.util.Stack; + +public class ClassStack implements Serializable { + + public Stack stack = new Stack(); + + public JavaClass pop() { + return (JavaClass) this.stack.pop(); + } + + public void push(JavaClass javaClass) { + this.stack.push(javaClass); + } + + public JavaClass top() { + return (JavaClass) this.stack.peek(); + } + + public boolean empty() { + return this.stack.empty(); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/util/ClassVector.java b/src/main/java/com/allatori/lib/bcel/util/ClassVector.java new file mode 100644 index 0000000..acb9cbd --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/util/ClassVector.java @@ -0,0 +1,32 @@ +package com.allatori.lib.bcel.util; + +import com.allatori.lib.bcel.classfile.JavaClass; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +/** + * @deprecated + */ +public class ClassVector implements Serializable { + + public List vec = new ArrayList(); + + public void addElement(JavaClass javaClass) { + this.vec.add(javaClass); + } + + public void removeElementAt(int value) { + this.vec.remove(value); + } + + public JavaClass elementAt(int value) { + return (JavaClass) this.vec.get(value); + } + + public JavaClass[] toArray() { + JavaClass[] javaClasss = new JavaClass[this.vec.size()]; + this.vec.toArray(javaClasss); + return javaClasss; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/util/CodeHTML.java b/src/main/java/com/allatori/lib/bcel/util/CodeHTML.java new file mode 100644 index 0000000..181233e --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/util/CodeHTML.java @@ -0,0 +1,827 @@ +package com.allatori.lib.bcel.util; + +import com.allatori.lib.bcel.Constants; +import com.allatori.lib.bcel.classfile.Attribute; +import com.allatori.lib.bcel.classfile.Code; +import com.allatori.lib.bcel.classfile.CodeException; +import com.allatori.lib.bcel.classfile.ConstantFieldref; +import com.allatori.lib.bcel.classfile.ConstantInterfaceMethodref; +import com.allatori.lib.bcel.classfile.ConstantMethodref; +import com.allatori.lib.bcel.classfile.ConstantNameAndType; +import com.allatori.lib.bcel.classfile.ConstantPool; +import com.allatori.lib.bcel.classfile.LocalVariable; +import com.allatori.lib.bcel.classfile.LocalVariableTable; +import com.allatori.lib.bcel.classfile.Method; +import com.allatori.lib.bcel.classfile.Utility; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.BitSet; + +public final class CodeHTML implements Constants { + + public String class_name; + + public Method[] methods; + + public PrintWriter file; + + public ConstantHTML constant_html; + + public static boolean wide = false; + + public ConstantPool constant_pool; + + public BitSet goto_set; + + public final String codeToHTML(ByteSequence byteSequence, int value) throws IOException { + short value2 = (short) byteSequence.readUnsignedByte(); + int value3 = 0; + byte value4 = 0; + StringBuffer stringBuffer; + (stringBuffer = new StringBuffer(256)) + .append("") + .append(TEXTS8[value2]) + .append(""); + if (value2 == 170 || value2 == 171) { + int value5; + value4 = (byte) ((value5 = byteSequence.getIndex() % 4) == 0 ? 0 : 4 - value5); + int value6; + for (int value7 = value6 = 0; value7 < value4; value7 = value6) { + value6++; + byteSequence.readByte(); + } + value3 = byteSequence.readInt(); + } + StringBuffer stringBuffer2; + switch (value2) { + case 18: + int value8 = byteSequence.readUnsignedByte(); + stringBuffer2 = stringBuffer; + stringBuffer + .append("") + .append( + Class2HTML.createText2( + this.constant_pool.getText( + value8, this.constant_pool.getConstant(value8).getTag()))) + .append(""); + break; + case 19: + case 20: + short value9 = byteSequence.readShort(); + stringBuffer2 = stringBuffer; + stringBuffer + .append("") + .append( + Class2HTML.createText2( + this.constant_pool.getText( + value9, this.constant_pool.getConstant(value9).getTag()))) + .append(""); + break; + case 21: + case 22: + case 23: + case 24: + case 25: + case 54: + case 55: + case 56: + case 57: + case 58: + case 169: + int value10; + if (wide) { + value10 = byteSequence.readShort(); + wide = false; + stringBuffer2 = stringBuffer; + } else { + value10 = byteSequence.readUnsignedByte(); + stringBuffer2 = stringBuffer; + } + stringBuffer2.append("%").append(value10); + stringBuffer2 = stringBuffer; + break; + case 26: + case 27: + case 28: + case 29: + case 30: + case 31: + case 32: + case 33: + case 34: + case 35: + case 36: + case 37: + case 38: + case 39: + case 40: + case 41: + case 42: + case 43: + case 44: + case 45: + case 46: + case 47: + case 48: + case 49: + case 50: + case 51: + case 52: + case 53: + case 59: + case 60: + case 61: + case 62: + case 63: + case 64: + case 65: + case 66: + case 67: + case 68: + case 69: + case 70: + case 71: + case 72: + case 73: + case 74: + case 75: + case 76: + case 77: + case 78: + case 79: + case 80: + case 81: + case 82: + case 83: + case 84: + case 85: + case 86: + case 87: + case 88: + case 89: + case 90: + case 91: + case 92: + case 93: + case 94: + case 95: + case 96: + case 97: + case 98: + case 99: + case 100: + case 101: + case 102: + case 103: + case 104: + case 105: + case 106: + case 107: + case 108: + case 109: + case 110: + case 111: + case 112: + case 113: + case 114: + case 115: + case 116: + case 117: + case 118: + case 119: + case 120: + case 121: + case 122: + case 123: + case 124: + case 125: + case 126: + case 127: + case 128: + case 129: + case 130: + case 131: + case 133: + case 134: + case 135: + case 136: + case 137: + case 138: + case 139: + case 140: + case 141: + case 142: + case 143: + case 144: + case 145: + case 146: + case 147: + case 148: + case 149: + case 150: + case 151: + case 152: + case 172: + case 173: + case 174: + case 175: + case 176: + case 177: + case 186: + case 190: + case 191: + case 194: + case 195: + default: + int value11; + if (NO_OF_OPERANDS[value2] > 0) { + for (int value12 = value11 = 0; + value12 < TYPE_OF_OPERANDS[value2].length; + value12 = value11) { + switch (TYPE_OF_OPERANDS[value2][value11]) { + case 8: + stringBuffer2 = stringBuffer; + stringBuffer.append(byteSequence.readUnsignedByte()); + break; + case 9: + stringBuffer2 = stringBuffer; + stringBuffer.append(byteSequence.readShort()); + break; + case 10: + stringBuffer2 = stringBuffer; + stringBuffer.append(byteSequence.readInt()); + break; + default: + System.err.println("Unreachable default case reached!"); + System.exit(-1); + stringBuffer2 = stringBuffer; + } + StringBuffer stringBuffer3 = stringBuffer2; + value11++; + stringBuffer3.append(" "); + } + } + stringBuffer2 = stringBuffer; + break; + case 132: + int value13; + short value14; + if (wide) { + value13 = byteSequence.readShort(); + stringBuffer2 = stringBuffer; + value14 = byteSequence.readShort(); + wide = false; + } else { + value13 = byteSequence.readUnsignedByte(); + stringBuffer2 = stringBuffer; + value14 = byteSequence.readByte(); + } + stringBuffer2.append("%").append(value13).append(" ").append(value14); + stringBuffer2 = stringBuffer; + break; + case 153: + case 154: + case 155: + case 156: + case 157: + case 158: + case 159: + case 160: + case 161: + case 162: + case 163: + case 164: + case 165: + case 166: + case 167: + case 168: + case 198: + case 199: + int value15 = byteSequence.getIndex() + byteSequence.readShort() - 1; + stringBuffer2 = stringBuffer; + stringBuffer + .append("") + .append(value15) + .append(""); + break; + case 170: + int value16 = byteSequence.readInt(); + int value17 = byteSequence.readInt(); + int value18 = byteSequence.getIndex() - 12 - value4 - 1; + int value19 = value3 + value18; + stringBuffer.append(""); + int[] values = new int[value17 - value16 + 1]; + int value20 = 0; + for (int value21 = value20; value21 < values.length; value21 = value20) { + values[value20] = value18 + byteSequence.readInt(); + StringBuffer stringBuffer4 = stringBuffer.append(""); + } + stringBuffer.append("\n"); + int value22 = 0; + for (int value23 = value22; value23 < values.length; value23 = value22) { + StringBuffer stringBuffer5 = + stringBuffer + .append(""); + } + stringBuffer2 = stringBuffer; + stringBuffer + .append("\n
").append(value16 + value20); + value20++; + stringBuffer4.append("default
") + .append(values[value22]); + value22++; + stringBuffer5.append("") + .append(value19) + .append("
\n"); + break; + case 171: + int value24 = byteSequence.readInt(); + int value25 = byteSequence.getIndex() - 8 - value4 - 1; + int[] values2 = new int[value24]; + int value26 = value3 + value25; + stringBuffer.append(""); + int value27 = 0; + for (int value28 = value27; value28 < value24; value28 = value27) { + int value29 = byteSequence.readInt(); + values2[value27] = value25 + byteSequence.readInt(); + StringBuffer stringBuffer6 = stringBuffer.append(""); + } + stringBuffer.append("\n"); + int value30 = 0; + for (int value31 = value30; value31 < value24; value31 = value30) { + StringBuffer stringBuffer7 = + stringBuffer + .append(""); + } + stringBuffer2 = stringBuffer; + stringBuffer + .append("\n
").append(value29); + value27++; + stringBuffer6.append("default
") + .append(values2[value30]); + value30++; + stringBuffer7.append("") + .append(value26) + .append("
\n"); + break; + case 178: + case 179: + case 180: + case 181: + short value32 = byteSequence.readShort(); + ConstantFieldref constantFieldref = + (ConstantFieldref) this.constant_pool.getConstant(value32, (byte) 9); + int class_index = constantFieldref.getClass_index(); + String text = Utility.getText(this.constant_pool.createText(class_index, (byte) 7), false); + int name_and_type_index = constantFieldref.getName_and_type_index(); + String text2 = this.constant_pool.getText(name_and_type_index, (byte) 12); + if (text.equals(this.class_name)) { + stringBuffer + .append("") + .append(text2) + .append("\n"); + stringBuffer2 = stringBuffer; + } else { + stringBuffer + .append(this.constant_html.referenceConstant(class_index)) + .append(".") + .append(text2); + stringBuffer2 = stringBuffer; + } + break; + case 182: + case 183: + case 184: + case 185: + short value33 = byteSequence.readShort(); + int value34; + int value35; + if (value2 == 185) { + byteSequence.readUnsignedByte(); + byteSequence.readUnsignedByte(); + ConstantInterfaceMethodref constantInterfaceMethodref = + (ConstantInterfaceMethodref) this.constant_pool.getConstant(value33, (byte) 11); + int class_index2 = constantInterfaceMethodref.getClass_index(); + this.constant_pool.constantToString(constantInterfaceMethodref); + value34 = constantInterfaceMethodref.getName_and_type_index(); + value35 = class_index2; + } else { + ConstantMethodref constantMethodref = + (ConstantMethodref) this.constant_pool.getConstant(value33, (byte) 10); + int class_index3 = constantMethodref.getClass_index(); + this.constant_pool.constantToString(constantMethodref); + value34 = constantMethodref.getName_and_type_index(); + value35 = class_index3; + } + String text3 = Class2HTML.referenceClass(value35); + String text4 = + Class2HTML.createText2( + this.constant_pool.constantToString( + this.constant_pool.getConstant(value34, (byte) 12))); + ConstantNameAndType constantNameAndType = + (ConstantNameAndType) this.constant_pool.getConstant(value34, (byte) 12); + String text5 = + this.constant_pool.getText(constantNameAndType.getSignature_index(), (byte) 1); + String[] texts = Utility.methodSignatureArgumentTypes(text5, false); + String text6 = Utility.createText(text5, false); + stringBuffer + .append(text3) + .append(".") + .append(text4) + .append("") + .append("("); + int value36 = 0; + for (int value37 = value36; value37 < texts.length; value37 = ++value36) { + stringBuffer.append(Class2HTML.createText(texts[value36])); + if (value36 < texts.length - 1) { + stringBuffer.append(", "); + } + } + stringBuffer2 = stringBuffer; + stringBuffer.append("):").append(Class2HTML.createText(text6)); + break; + case 187: + case 192: + case 193: + short value38 = byteSequence.readShort(); + stringBuffer2 = stringBuffer; + stringBuffer.append(this.constant_html.referenceConstant(value38)); + break; + case 188: + stringBuffer2 = stringBuffer; + stringBuffer + .append("") + .append(TEXTS[byteSequence.readByte()]) + .append(""); + break; + case 189: + short value39 = byteSequence.readShort(); + stringBuffer2 = stringBuffer; + stringBuffer.append(this.constant_html.referenceConstant(value39)); + break; + case 196: + wide = true; + stringBuffer2 = stringBuffer; + stringBuffer.append("(wide)"); + break; + case 197: + short value40 = byteSequence.readShort(); + byte value41 = byteSequence.readByte(); + stringBuffer2 = stringBuffer; + stringBuffer + .append(this.constant_html.referenceConstant(value40)) + .append(":") + .append(value41) + .append("-dimensional"); + break; + case 200: + case 201: + int value42 = byteSequence.getIndex() + byteSequence.readInt() - 1; + stringBuffer2 = stringBuffer; + stringBuffer + .append("") + .append(value42) + .append(""); + } + stringBuffer2.append(""); + return stringBuffer.toString(); + } + + public void writeMethod(Method method, int value) throws IOException { + String text2 = method.getText2(); + String[] texts = Utility.methodSignatureArgumentTypes(text2, false); + String text = Utility.createText(text2, false); + String text3 = Class2HTML.createText2(method.getText()); + String text4 = Utility.replace(Utility.getText2(method.getAccess_flags2()), " ", " "); + Attribute[] attributes = method.getAttributes(); + PrintWriter printWriter = this.file; + StringBuilder stringBuilder = new StringBuilder(); + int value2 = 0; + printWriter.print( + stringBuilder + .insert(0, "

") + .append(text4) + .append(" ") + .append("") + .append(Class2HTML.createText(text)) + .append(" ") + .append(text3) + .append("(") + .toString()); + for (int index = 0; value2 < texts.length; value2 = ++index) { + this.file.print(Class2HTML.createText(texts[index])); + if (index < texts.length - 1) { + this.file.print(", "); + } + } + this.file.println(")

"); + Code code = null; + byte[] values = null; + if (attributes.length > 0) { + int value3 = 0; + this.file.print("

Attributes

    \n"); + for (int index2 = 0; value3 < attributes.length; value3 = ++index2) { + byte value4; + byte value5; + if ((value4 = attributes[index2].getTag()) != -1) { + value5 = value4; + this.file.print( + "
  • " + + TEXTS4[value4] + + "
  • \n"); + } else { + this.file.print("
  • " + attributes[index2] + "
  • "); + value5 = value4; + } + if (value5 == 2) { + Code code2 = code = (Code) attributes[index2]; + Attribute[] attributes2 = code2.getAttributes(); + values = code2.getCode(); + int value6 = 0; + this.file.print(""); + } + } + this.file.println("
"); + } + if (values != null) { + ByteSequence byteSequence = new ByteSequence(values); + ByteSequence byteSequence2 = byteSequence; + byteSequence.mark(byteSequence.available()); + this.findGotos(byteSequence, method, code); + byteSequence.reset(); + this.file.println( + "Argument"); + int value7 = 0; + while (byteSequence2.available() > 0) { + int index4 = byteSequence.getIndex(); + String text5 = this.codeToHTML(byteSequence, value); + String text6 = ""; + if (this.goto_set.get(index4)) { + text6 = ""; + } + String text7; + CodeHTML codeHTML; + if (byteSequence.getIndex() == values.length) { + text7 = "" + index4 + ""; + codeHTML = this; + } else { + text7 = "" + index4; + codeHTML = this; + } + printWriter = codeHTML.file; + StringBuilder stringBuilder3 = + new StringBuilder() + .insert(0, "").toString()); + byteSequence2 = byteSequence; + } + this.file.println(""); + this.file.println("
Byte
offset
Instruction
") + .append(text7) + .append("") + .append(text6) + .append(text5); + PrintWriter printWriter3 = printWriter; + value7++; + printWriter3.println(stringBuilder3.append((String) "
"); + } + } + + public final void findGotos(ByteSequence byteSequence, Method method, Code code) + throws IOException { + this.goto_set = new BitSet(byteSequence.available()); + if (code != null) { + CodeException[] codeExceptions; + int value = (codeExceptions = code.getExceptionTable()).length; + int value2; + for (int value3 = value2 = 0; value3 < value; value3 = value2) { + this.goto_set.set(codeExceptions[value2].getStart_pc()); + this.goto_set.set(codeExceptions[value2].getEnd_pc()); + int value4 = value2; + CodeException[] codeExceptions2 = codeExceptions; + BitSet bitSet = this.goto_set; + value2++; + bitSet.set(codeExceptions2[value4].getHandler_pc()); + } + Attribute[] attributes = code.getAttributes(); + int value5; + for (int value6 = value5 = 0; value6 < attributes.length; value6 = ++value5) { + if (attributes[value5].getTag() == 5) { + LocalVariable[] localVariableTable = + ((LocalVariableTable) attributes[value5]).getLocalVariableTable(); + int value7; + for (int value8 = value7 = 0; value8 < localVariableTable.length; value8 = value7) { + int value9; + int value10 = + (value9 = localVariableTable[value7].getStart_pc()) + + localVariableTable[value7].getLength(); + this.goto_set.set(value9); + value7++; + this.goto_set.set(value10); + } + break; + } + } + } + int value11 = 0; + for (ByteSequence byteSequence2 = byteSequence; + byteSequence2.available() > 0; + byteSequence2 = byteSequence) { + int value12; + switch (value12 = byteSequence.readUnsignedByte()) { + case 153: + case 154: + case 155: + case 156: + case 157: + case 158: + case 159: + case 160: + case 161: + case 162: + case 163: + case 164: + case 165: + case 166: + case 167: + case 168: + case 198: + case 199: + int value13 = byteSequence.getIndex() + byteSequence.readShort() - 1; + this.goto_set.set(value13); + break; + case 169: + case 172: + case 173: + case 174: + case 175: + case 176: + case 177: + case 178: + case 179: + case 180: + case 181: + case 182: + case 183: + case 184: + case 185: + case 186: + case 187: + case 188: + case 189: + case 190: + case 191: + case 192: + case 193: + case 194: + case 195: + case 196: + case 197: + default: + byteSequence.unreadByte(); + this.codeToHTML(byteSequence, 0); + break; + case 170: + case 171: + int value14; + int value15 = (value14 = byteSequence.getIndex() % 4) == 0 ? 0 : 4 - value14; + int value16; + for (int value17 = value16 = 0; value17 < value15; value17 = value16) { + value16++; + byteSequence.readByte(); + } + int value18 = byteSequence.readInt(); + if (value12 == 170) { + int value19 = byteSequence.readInt(); + int value20 = byteSequence.readInt(); + int value21 = byteSequence.getIndex() - 12 - value15 - 1; + int value22 = value18 + value21; + this.goto_set.set(value22); + int value23; + for (int value24 = value23 = 0; value24 < value20 - value19 + 1; value24 = value23) { + int value25 = value21 + byteSequence.readInt(); + value23++; + this.goto_set.set(value25); + } + } else { + int value26 = byteSequence.readInt(); + int value27 = byteSequence.getIndex() - 8 - value15 - 1; + int value28 = value18 + value27; + int value29 = 0; + this.goto_set.set(value28); + for (int index = 0; value29 < value26; value29 = index) { + byteSequence.readInt(); + int value30 = value27 + byteSequence.readInt(); + index++; + this.goto_set.set(value30); + } + } + break; + case 200: + case 201: + int value31 = byteSequence.getIndex() + byteSequence.readInt() - 1; + this.goto_set.set(value31); + } + value11++; + } + } + + public CodeHTML( + String text, + String class_name, + Method[] methods2, + ConstantPool constantPool, + ConstantHTML constantHTML) + throws IOException { + super(); + int value = 0; + this.class_name = class_name; + this.methods = methods2; + this.constant_pool = constantPool; + this.constant_html = constantHTML; + this.file = new PrintWriter(new FileOutputStream(("" + text + class_name + "_code.html"))); + this.file.println(""); + for (int index = 0; value < methods2.length; value = index) { + Method method = methods2[index]; + int value2 = index; + index++; + this.writeMethod(method, value2); + } + this.file.println(""); + this.file.close(); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/util/ConstantHTML.java b/src/main/java/com/allatori/lib/bcel/util/ConstantHTML.java new file mode 100644 index 0000000..8279b31 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/util/ConstantHTML.java @@ -0,0 +1,334 @@ +package com.allatori.lib.bcel.util; + +import com.allatori.lib.bcel.Constants; +import com.allatori.lib.bcel.classfile.Constant; +import com.allatori.lib.bcel.classfile.ConstantClass; +import com.allatori.lib.bcel.classfile.ConstantFieldref; +import com.allatori.lib.bcel.classfile.ConstantInterfaceMethodref; +import com.allatori.lib.bcel.classfile.ConstantMethodref; +import com.allatori.lib.bcel.classfile.ConstantNameAndType; +import com.allatori.lib.bcel.classfile.ConstantPool; +import com.allatori.lib.bcel.classfile.ConstantString; +import com.allatori.lib.bcel.classfile.Method; +import com.allatori.lib.bcel.classfile.Utility; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintWriter; + +public final class ConstantHTML implements Constants { + + public PrintWriter file; + + public String class_name; + + public Method[] methods; + + public String[] constant_ref; + + public String class_package; + + public ConstantPool constant_pool; + + public Constant[] constants; + + public String referenceConstant(int value) { + return this.constant_ref[value]; + } + + public final int getMethodNumber(String text) { + int value; + for (int value2 = value = 0; value2 < this.methods.length; value2 = ++value) { + if (("" + this.methods[value].getText() + this.methods[value].getText2()).equals(text)) { + return value; + } + } + return -1; + } + + public ConstantHTML( + String text, + String class_name, + String class_package, + Method[] methods2, + ConstantPool constantPool) + throws IOException { + super(); + this.class_name = class_name; + this.class_package = class_package; + this.constant_pool = constantPool; + this.methods = methods2; + this.constants = constantPool.getConstantPool(); + this.file = new PrintWriter(new FileOutputStream(("" + text + class_name + "_cp.html"))); + this.constant_ref = new String[this.constants.length]; + int value = 1; + this.constant_ref[0] = "<unknown>"; + this.file.println(""); + for (int index = 1; value < this.constants.length; value = index) { + ConstantHTML constantHTML; + if (index % 2 == 0) { + constantHTML = this; + this.file.print("\n"); + } + this.file.println("
"); + } else { + constantHTML = this; + this.file.print("
"); + } + if (constantHTML.constants[index] != null) { + this.writeConstant(index); + } + PrintWriter printWriter = this.file; + index++; + printWriter.print("
"); + this.file.close(); + } + + public void writeConstant(int value) { + byte tag = this.constants[value].getTag(); + this.file.println("

" + value + " " + TEXTS7[tag] + "

"); + switch (tag) { + case 7: + int nameIndex = + ((ConstantClass) this.constant_pool.getConstant(value, (byte) 7)).getNameIndex(); + String text; + String text2 = + Utility.compactClassName( + Utility.getText(text = this.constant_pool.getText(value, tag)), + "" + this.class_package + ".", + true); + String text3 = "" + text2 + ""; + this.constant_ref[value] = + "" + + text2 + + ""; + this.file.println( + "

" + + text3 + + "

\n"); + return; + case 8: + int stringIndex = + ((ConstantString) this.constant_pool.getConstant(value, (byte) 8)).getStringIndex(); + String text4 = Class2HTML.createText2(this.constant_pool.getText(value, tag)); + this.file.println( + "

" + + text4 + + "

\n"); + return; + case 9: + ConstantFieldref constantFieldref = + (ConstantFieldref) this.constant_pool.getConstant(value, (byte) 9); + int class_index = constantFieldref.getClass_index(); + int name_and_type_index = constantFieldref.getName_and_type_index(); + String text5; + String text6 = + Utility.compactClassName( + Utility.getText(text5 = this.constant_pool.getText(class_index, (byte) 7)), + "" + this.class_package + ".", + true); + String text7 = this.constant_pool.getText(name_and_type_index, (byte) 12); + boolean matches = text5.equals(this.class_name); + StringBuilder stringBuilder = new StringBuilder(); + String text8; + ConstantHTML constantHTML; + if (matches) { + text8 = + stringBuilder + .insert(0, "") + .append(text7) + .append("") + .toString(); + constantHTML = this; + } else { + text8 = + stringBuilder + .insert(0, "") + .append(text6) + .append(".") + .append(text7) + .append("\n") + .toString(); + constantHTML = this; + } + constantHTML.constant_ref[value] = + "" + + text6 + + "." + + text7 + + ""; + this.file.println( + "

" + + text8 + + "
\n" + + "

"); + return; + case 10: + case 11: + int value2; + int value3; + ConstantHTML constantHTML2; + if (tag == 10) { + ConstantMethodref constantMethodref = + (ConstantMethodref) this.constant_pool.getConstant(value, (byte) 10); + constantHTML2 = this; + value3 = constantMethodref.getClass_index(); + value2 = constantMethodref.getName_and_type_index(); + } else { + ConstantInterfaceMethodref constantInterfaceMethodref = + (ConstantInterfaceMethodref) this.constant_pool.getConstant(value, (byte) 11); + constantHTML2 = this; + value3 = constantInterfaceMethodref.getClass_index(); + value2 = constantInterfaceMethodref.getName_and_type_index(); + } + String text9; + String text10 = + Class2HTML.createText2(text9 = constantHTML2.constant_pool.getText(value2, (byte) 12)); + String text11; + String text12 = text11 = this.constant_pool.getText(value3, (byte) 7); + Utility.getText(text12); + String text13 = Utility.getText(text12); + String text14 = Utility.compactClassName(text13, this.class_package + ".", true); + ConstantNameAndType constantNameAndType = + (ConstantNameAndType) this.constant_pool.getConstant(value2, (byte) 12); + String text15; + String text16 = + text15 = this.constant_pool.getText(constantNameAndType.getSignature_index(), (byte) 1); + String[] texts = Utility.methodSignatureArgumentTypes(text16, false); + String text17 = Class2HTML.createText(Utility.createText(text16, false)); + StringBuffer stringBuffer = new StringBuffer("("); + int value4; + for (int value5 = value4 = 0; value5 < texts.length; value5 = ++value4) { + stringBuffer.append(Class2HTML.createText(texts[value4])); + if (value4 < texts.length - 1) { + stringBuffer.append(", "); + } + } + stringBuffer.append(")"); + String text18 = stringBuffer.toString(); + boolean matches2 = text11.equals(this.class_name); + StringBuilder stringBuilder2 = new StringBuilder(); + String text19; + if (matches2) { + text19 = + stringBuilder2 + .insert(0, "") + .append(text10) + .append("") + .toString(); + constantHTML2 = this; + } else { + text19 = + stringBuilder2 + .insert(0, "") + .append(text14) + .append(".") + .append(text10) + .toString(); + constantHTML2 = this; + } + constantHTML2.constant_ref[value] = + "" + + text17 + + " " + + text14 + + "." + + text10 + + " " + + text18; + this.file.println( + "

" + + text17 + + " " + + text19 + + text18 + + " \n

"); + return; + case 12: + ConstantNameAndType constantNameAndType2 = + (ConstantNameAndType) this.constant_pool.getConstant(value, (byte) 12); + int name_index = constantNameAndType2.getName_index(); + int signature_index = constantNameAndType2.getSignature_index(); + this.file.println( + "

" + + Class2HTML.createText2(this.constant_pool.getText(value, tag)) + + "

\n"); + return; + default: + this.file.println( + "

" + Class2HTML.createText2(this.constant_pool.getText(value, tag)) + "\n"); + } + } +} diff --git a/src/main/java/com/allatori/lib/bcel/util/InstructionFinder$CodeConstraint.java b/src/main/java/com/allatori/lib/bcel/util/InstructionFinder$CodeConstraint.java new file mode 100644 index 0000000..6fe6574 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/util/InstructionFinder$CodeConstraint.java @@ -0,0 +1,8 @@ +package com.allatori.lib.bcel.util; + +import com.allatori.lib.bcel.generic.InstructionHandle; + +public interface InstructionFinder$CodeConstraint { + + boolean checkCode(InstructionHandle[] instructionHandles); +} diff --git a/src/main/java/com/allatori/lib/bcel/util/InstructionFinder.java b/src/main/java/com/allatori/lib/bcel/util/InstructionFinder.java new file mode 100644 index 0000000..b6cc5ef --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/util/InstructionFinder.java @@ -0,0 +1,293 @@ +package com.allatori.lib.bcel.util; + +import com.allatori.lib.bcel.Constants; +import com.allatori.lib.bcel.generic.ClassGenException; +import com.allatori.lib.bcel.generic.InstructionHandle; +import com.allatori.lib.bcel.generic.InstructionList; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Locale; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class InstructionFinder { + + public static final int OFFSET = 32767; + + public static final int NO_OPCODES = 256; + + public String il_string; + + public static final Map map = new HashMap(); + + public InstructionList il; + + public InstructionHandle[] handles; + + public final void reread() { + int value; + char[] values = new char[value = this.il.getLength2()]; + this.handles = this.il.getInstructionHandles(); + int value2; + for (int value3 = value2 = 0; value3 < value; value3 = value2) { + char value4 = makeChar(this.handles[value2].getInstruction().getOpcode()); + int value5 = value2; + value2++; + values[value5] = value4; + } + this.il_string = new String(values); + } + + public final InstructionList getInstructionList() { + return this.il; + } + + public final Iterator search(String text) { + return this.search(text, this.il.getStart(), null); + } + + public static final String getText(String text) { + return pattern2string(text, true); + } + + public static final String compilePattern(String text) { + String text2 = text.toLowerCase(Locale.ENGLISH); + StringBuffer stringBuffer = new StringBuffer(); + int size = text.length(); + int value; + for (int value2 = value = 0; value2 < size; value2 = ++value) { + char value3; + if (!Character.isLetterOrDigit(value3 = text2.charAt(value))) { + if (!Character.isWhitespace(value3)) { + stringBuffer.append(value3); + } + } else { + StringBuffer stringBuffer2 = new StringBuffer(); + for (char value4 = value3; + (Character.isLetterOrDigit(value4) || value3 == '_') && value < size; + value4 = value3 = text2.charAt(value)) { + value++; + stringBuffer2.append(value3); + if (value >= size) { + break; + } + } + value--; + stringBuffer.append(createText(stringBuffer2.toString())); + } + } + return stringBuffer.toString(); + } + + static { + map.put( + "arithmeticinstruction", + "(irem|lrem|iand|ior|ineg|isub|lneg|fneg|fmul|ldiv|fadd|lxor|frem|idiv|land|ixor|ishr|fsub|lshl|fdiv|iadd|lor|dmul|lsub|ishl|imul|lmul|lushr|dneg|iushr|lshr|ddiv|drem|dadd|ladd|dsub)"); + map.put("invokeinstruction", "(invokevirtual|invokeinterface|invokestatic|invokespecial)"); + map.put( + "arrayinstruction", + "(baload|aastore|saload|caload|fastore|lastore|iaload|castore|iastore|aaload|bastore|sastore|faload|laload|daload|dastore)"); + map.put("gotoinstruction", "(goto|goto_w)"); + map.put( + "conversioninstruction", "(d2l|l2d|i2s|d2i|l2i|i2b|l2f|d2f|f2i|i2d|i2l|f2d|i2c|f2l|i2f)"); + map.put( + "localvariableinstruction", + "(fstore|iinc|lload|dstore|dload|iload|aload|astore|istore|fload|lstore)"); + map.put("loadinstruction", "(fload|dload|lload|iload|aload)"); + map.put("fieldinstruction", "(getfield|putstatic|getstatic|putfield)"); + map.put( + "cpinstruction", + "(ldc2_w|invokeinterface|multianewarray|putstatic|instanceof|getstatic|checkcast|getfield|invokespecial|ldc_w|invokestatic|invokevirtual|putfield|ldc|new|anewarray)"); + map.put("stackinstruction", "(dup2|swap|dup2_x2|pop|pop2|dup|dup2_x1|dup_x2|dup_x1)"); + map.put( + "branchinstruction", + "(ifle|if_acmpne|if_icmpeq|if_acmpeq|ifnonnull|goto_w|iflt|ifnull|if_icmpne|tableswitch|if_icmple|ifeq|if_icmplt|jsr_w|if_icmpgt|ifgt|jsr|goto|ifne|ifge|lookupswitch|if_icmpge)"); + map.put("returninstruction", "(lreturn|ireturn|freturn|dreturn|areturn|return)"); + map.put("storeinstruction", "(istore|fstore|dstore|astore|lstore)"); + map.put("select", "(tableswitch|lookupswitch)"); + map.put( + "ifinstruction", + "(ifeq|ifgt|if_icmpne|if_icmpeq|ifge|ifnull|ifne|if_icmple|if_icmpge|if_acmpeq|if_icmplt|if_acmpne|ifnonnull|iflt|if_icmpgt|ifle)"); + map.put("jsrinstruction", "(jsr|jsr_w)"); + map.put("variablelengthinstruction", "(tableswitch|jsr|goto|lookupswitch)"); + map.put("unconditionalbranch", "(goto|jsr|jsr_w|athrow|goto_w)"); + map.put("constantpushinstruction", "(dconst|bipush|sipush|fconst|iconst|lconst)"); + map.put( + "typedinstruction", + "(imul|lsub|aload|fload|lor|new|aaload|fcmpg|iand|iaload|lrem|idiv|d2l|isub|dcmpg|dastore|ret|f2d|f2i|drem|iinc|i2c|checkcast|frem|lreturn|astore|lushr|daload|dneg|fastore|istore|lshl|ldiv|lstore|areturn|ishr|ldc_w|invokeinterface|aastore|lxor|ishl|l2d|i2f|return|faload|sipush|iushr|caload|instanceof|invokespecial|putfield|fmul|ireturn|laload|d2f|lneg|ixor|i2l|fdiv|lastore|multianewarray|i2b|getstatic|i2d|putstatic|fcmpl|saload|ladd|irem|dload|jsr_w|dconst|dcmpl|fsub|freturn|ldc|aconst_null|castore|lmul|ldc2_w|dadd|iconst|f2l|ddiv|dstore|land|jsr|anewarray|dmul|bipush|dsub|sastore|d2i|i2s|lshr|iadd|l2i|lload|bastore|fstore|fneg|iload|fadd|baload|fconst|ior|ineg|dreturn|l2f|lconst|getfield|invokevirtual|invokestatic|iastore)"); + map.put("popinstruction", "(fstore|dstore|pop|pop2|astore|putstatic|istore|lstore)"); + map.put("allocationinstruction", "(multianewarray|new|anewarray|newarray)"); + map.put( + "indexedinstruction", + "(lload|lstore|fload|ldc2_w|invokeinterface|multianewarray|astore|dload|putstatic|instanceof|getstatic|checkcast|getfield|invokespecial|dstore|istore|iinc|ldc_w|ret|fstore|invokestatic|iload|putfield|invokevirtual|ldc|new|aload|anewarray)"); + map.put( + "pushinstruction", + "(dup|lload|dup2|bipush|fload|ldc2_w|sipush|lconst|fconst|dload|getstatic|ldc_w|aconst_null|dconst|iload|ldc|iconst|aload)"); + map.put( + "stackproducer", + "(imul|lsub|aload|fload|lor|new|aaload|fcmpg|iand|iaload|lrem|idiv|d2l|isub|dcmpg|dup|f2d|f2i|drem|i2c|checkcast|frem|lushr|daload|dneg|lshl|ldiv|ishr|ldc_w|invokeinterface|lxor|ishl|l2d|i2f|faload|sipush|iushr|caload|instanceof|invokespecial|fmul|laload|d2f|lneg|ixor|i2l|fdiv|getstatic|i2b|swap|i2d|dup2|fcmpl|saload|ladd|irem|dload|jsr_w|dconst|dcmpl|fsub|ldc|arraylength|aconst_null|tableswitch|lmul|ldc2_w|iconst|dadd|f2l|ddiv|land|jsr|anewarray|dmul|bipush|dsub|d2i|newarray|i2s|lshr|iadd|lload|l2i|fneg|iload|fadd|baload|fconst|lookupswitch|ior|ineg|lconst|l2f|getfield|invokevirtual|invokestatic)"); + map.put( + "stackconsumer", + "(imul|lsub|lor|iflt|fcmpg|if_icmpgt|iand|ifeq|if_icmplt|lrem|ifnonnull|idiv|d2l|isub|dcmpg|dastore|if_icmpeq|f2d|f2i|drem|i2c|checkcast|frem|lreturn|astore|lushr|pop2|monitorexit|dneg|fastore|istore|lshl|ldiv|lstore|areturn|if_icmpge|ishr|monitorenter|invokeinterface|aastore|lxor|ishl|l2d|i2f|return|iushr|instanceof|invokespecial|fmul|ireturn|d2f|lneg|ixor|pop|i2l|ifnull|fdiv|lastore|i2b|if_acmpeq|ifge|swap|i2d|putstatic|fcmpl|ladd|irem|dcmpl|fsub|freturn|ifgt|castore|lmul|dadd|f2l|ddiv|dstore|land|if_icmpne|if_acmpne|dmul|dsub|sastore|ifle|d2i|i2s|lshr|iadd|l2i|bastore|fstore|fneg|fadd|ior|ineg|ifne|dreturn|l2f|if_icmple|getfield|invokevirtual|invokestatic|iastore)"); + map.put( + "exceptionthrower", + "(irem|lrem|laload|putstatic|baload|dastore|areturn|getstatic|ldiv|anewarray|iastore|castore|idiv|saload|lastore|fastore|putfield|lreturn|caload|getfield|return|aastore|freturn|newarray|instanceof|multianewarray|athrow|faload|iaload|aaload|dreturn|monitorenter|checkcast|bastore|arraylength|new|invokevirtual|sastore|ldc_w|ireturn|invokespecial|monitorexit|invokeinterface|ldc|invokestatic|daload)"); + map.put( + "loadclass", + "(multianewarray|invokeinterface|instanceof|invokespecial|putfield|checkcast|putstatic|invokevirtual|new|getstatic|invokestatic|getfield|anewarray)"); + map.put( + "instructiontargeter", + "(ifle|if_acmpne|if_icmpeq|if_acmpeq|ifnonnull|goto_w|iflt|ifnull|if_icmpne|tableswitch|if_icmple|ifeq|if_icmplt|jsr_w|if_icmpgt|ifgt|jsr|goto|ifne|ifge|lookupswitch|if_icmpge)"); + map.put("if_icmp", "(if_icmpne|if_icmpeq|if_icmple|if_icmpge|if_icmplt|if_icmpgt)"); + map.put("if_acmp", "(if_acmpeq|if_acmpne)"); + map.put("if", "(ifeq|ifne|iflt|ifge|ifgt|ifle)"); + map.put("iconst", precompile((short) 3, (short) 8, (short) 2)); + map.put( + "lconst", + new String(new char[] {'(', makeChar((short) 9), '|', makeChar((short) 10), ')'})); + map.put( + "dconst", + new String(new char[] {'(', makeChar((short) 14), '|', makeChar((short) 15), ')'})); + map.put( + "fconst", + new String(new char[] {'(', makeChar((short) 11), '|', makeChar((short) 12), ')'})); + map.put("iload", precompile((short) 26, (short) 29, (short) 21)); + map.put("dload", precompile((short) 38, (short) 41, (short) 24)); + map.put("fload", precompile((short) 34, (short) 37, (short) 23)); + map.put("aload", precompile((short) 42, (short) 45, (short) 25)); + map.put("istore", precompile((short) 59, (short) 62, (short) 54)); + map.put("dstore", precompile((short) 71, (short) 74, (short) 57)); + map.put("fstore", precompile((short) 67, (short) 70, (short) 56)); + map.put("astore", precompile((short) 75, (short) 78, (short) 58)); + for (String text : ((Iterable) ((Iterable) map.keySet()))) { + String text2; + if ((text2 = (String) map.get(text)).charAt(1) < 32767) { + map.put(text, compilePattern(text2)); + } + } + StringBuffer stringBuffer = new StringBuffer("("); + short value; + for (short value2 = value = 0; value2 < 256; value2 = ++value) { + if (Constants.NO_OF_OPERANDS[value] != -1) { + stringBuffer.append(makeChar(value)); + if (value < 255) { + stringBuffer.append('|'); + } + } + } + stringBuffer.append(')'); + map.put("instruction", stringBuffer.toString()); + } + + public InstructionFinder(InstructionList instructionList) { + super(); + this.il = instructionList; + this.reread(); + } + + public final Iterator search( + String text, InstructionFinder$CodeConstraint instructionFinder$CodeConstraint) { + return this.search(text, this.il.getStart(), instructionFinder$CodeConstraint); + } + + public final Iterator search( + String text, + InstructionHandle instructionHandle, + InstructionFinder$CodeConstraint instructionFinder$CodeConstraint) { + String text2 = compilePattern(text); + int value = -1; + int value2; + int value3 = value2 = 0; + while (true) { + if (value3 >= this.handles.length) { + value3 = value; + break; + } + if (this.handles[value2] == instructionHandle) { + value3 = value = value2; + break; + } + value3 = ++value2; + } + if (value3 == -1) { + throw new ClassGenException( + ("Instruction handle " + instructionHandle + " not found in instruction list.")); + } + Pattern pattern = Pattern.compile(text2); + ArrayList values = new ArrayList(); + Matcher matcher2 = pattern.matcher(this.il_string); + value3 = value; + while (value3 < this.il_string.length() && matcher2.find(value)) { + int value4 = matcher2.start(); + int value5; + int value6 = (value5 = matcher2.end()) - value4 + 1; + InstructionHandle[] match = this.getMatch(value4, value6); + if (instructionFinder$CodeConstraint == null + || instructionFinder$CodeConstraint.checkCode(match)) { + values.add(match); + } + value3 = value = value5; + } + return values.iterator(); + } + + public static final String createText(String text) { + String text2; + if ((text2 = (String) map.get(text)) != null) { + return text2; + } + int value; + for (int value2 = value = 0; value2 < 256; value2 = ++value) { + if (text.equals(Constants.TEXTS8[value])) { + return "" + makeChar((short) value); + } + } + throw new RuntimeException(("Instruction unknown: " + text)); + } + + public static final char makeChar(short value) { + return (char) (value + 32767); + } + + public static String precompile(short value, short value2, short value3) { + StringBuffer stringBuffer = new StringBuffer("("); + int value4; + for (int value5 = value4 = value; value5 <= value2; value5 = ++value4) { + stringBuffer.append(makeChar((short) value4)); + stringBuffer.append('|'); + } + stringBuffer.append(makeChar(value3)); + stringBuffer.append(")"); + return stringBuffer.toString(); + } + + public final Iterator search(String text, InstructionHandle instructionHandle) { + return this.search(text, instructionHandle, null); + } + + public static final String pattern2string(String text, boolean matches) { + StringBuffer stringBuffer = new StringBuffer(); + int value; + for (int value2 = value = 0; value2 < text.length(); value2 = ++value) { + char value3; + if ((value3 = text.charAt(value)) >= 32767) { + if (matches) { + stringBuffer.append(Constants.TEXTS8[value3 - 32767]); + } else { + stringBuffer.append(value3 - 32767); + } + } else { + stringBuffer.append(value3); + } + } + return stringBuffer.toString(); + } + + public InstructionHandle[] getMatch(int value, int value2) { + InstructionHandle[] instructionHandles = new InstructionHandle[value2]; + System.arraycopy(this.handles, value, instructionHandles, 0, value2); + return instructionHandles; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/util/JavaWrapper.java b/src/main/java/com/allatori/lib/bcel/util/JavaWrapper.java new file mode 100644 index 0000000..b34e442 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/util/JavaWrapper.java @@ -0,0 +1,66 @@ +package com.allatori.lib.bcel.util; + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +public class JavaWrapper { + + public java.lang.ClassLoader loader; + + public void runMain(String text, String[] texts) throws ClassNotFoundException { + Class classValue = this.loader.loadClass(text); + Method method; + try { + Method method2 = method = classValue.getMethod("main", texts.getClass()); + int modifiers = method2.getModifiers(); + Class returnType = method2.getReturnType(); + if (!Modifier.isPublic(modifiers) + || !Modifier.isStatic(modifiers) + || Modifier.isAbstract(modifiers) + || returnType != void.class) { + throw new NoSuchMethodException(); + } + } catch (NoSuchMethodException noSuchMethodException) { + System.out.println( + "In class " + text + ": public static void main(String[] argv) is not defined"); + return; + } + try { + method.invoke(null, texts); + } catch (Exception exception) { + exception.printStackTrace(); + } + } + + public static void main(String[] texts) throws Exception { + if (texts.length == 0) { + System.out.println("Missing class name."); + } else { + String text = texts[0]; + String[] texts2 = new String[texts.length - 1]; + System.arraycopy(texts, 1, texts2, 0, texts2.length); + new JavaWrapper().runMain(text, texts2); + } + } + + public static java.lang.ClassLoader getClassLoader() { + String text; + if ((text = System.getProperty("bcel.classloader")) == null || "".equals(text)) { + text = "com.allatori.lib.bcel.util.ClassLoader"; + } + try { + return (java.lang.ClassLoader) Class.forName(text).newInstance(); + } catch (Exception exception) { + throw new RuntimeException(exception.toString()); + } + } + + public JavaWrapper(java.lang.ClassLoader classLoader) { + super(); + this.loader = classLoader; + } + + public JavaWrapper() { + this(getClassLoader()); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/util/MethodHTML.java b/src/main/java/com/allatori/lib/bcel/util/MethodHTML.java new file mode 100644 index 0000000..4799ba9 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/util/MethodHTML.java @@ -0,0 +1,195 @@ +package com.allatori.lib.bcel.util; + +import com.allatori.lib.bcel.Constants; +import com.allatori.lib.bcel.classfile.Attribute; +import com.allatori.lib.bcel.classfile.Code; +import com.allatori.lib.bcel.classfile.ConstantValue; +import com.allatori.lib.bcel.classfile.ExceptionTable; +import com.allatori.lib.bcel.classfile.Field; +import com.allatori.lib.bcel.classfile.Method; +import com.allatori.lib.bcel.classfile.Utility; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintWriter; + +public final class MethodHTML implements Constants { + + public ConstantHTML constant_html; + + public String class_name; + + public AttributeHTML attribute_html; + + public PrintWriter file; + + public final void writeMethod(Method method, int value) throws IOException { + String text2 = method.getText2(); + String[] texts = Utility.methodSignatureArgumentTypes(text2, false); + String text = Utility.createText(text2, false); + String text3 = method.getText(); + String text22 = Utility.getText2(method.getAccess_flags2()); + Attribute[] attributes = method.getAttributes(); + String text4 = Utility.replace(text22, " ", " "); + String text5 = Class2HTML.createText2(text3); + this.file.print( + "" + + text4 + + ""); + PrintWriter printWriter = this.file; + StringBuilder stringBuilder = new StringBuilder(); + int value2 = 0; + printWriter.print( + stringBuilder + .insert(0, "") + .append(Class2HTML.createText(text)) + .append("") + .append("") + .append(text5) + .append("\n(") + .toString()); + for (int index = 0; value2 < texts.length; value2 = ++index) { + this.file.print(Class2HTML.createText(texts[index])); + if (index < texts.length - 1) { + this.file.print(", "); + } + } + this.file.print(")"); + int value3; + for (int value4 = value3 = 0; value4 < attributes.length; value4 = ++value3) { + this.attribute_html.writeAttribute( + attributes[value3], "method" + value + "@" + value3, value); + byte value5; + if ((value5 = attributes[value3].getTag()) != 3) { + if (value5 == 2) { + Attribute[] attributes2 = ((Code) attributes[value3]).getAttributes(); + int value6; + for (int value7 = value6 = 0; value7 < attributes2.length; value7 = value6) { + AttributeHTML attributeHTML = this.attribute_html; + Attribute attribute = attributes2[value6]; + StringBuilder stringBuilder2 = + new StringBuilder() + .insert(0, "method") + .append(value) + .append("@") + .append(value3) + .append("@") + .append(value6); + value6++; + attributeHTML.writeAttribute(attribute, stringBuilder2.toString(), value); + } + } + } else { + this.file.print("throws"); + int[] exceptionIndexTable = ((ExceptionTable) attributes[value3]).getExceptionIndexTable(); + int value8; + for (int value9 = value8 = 0; value9 < exceptionIndexTable.length; value9 = ++value8) { + this.file.print(this.constant_html.referenceConstant(exceptionIndexTable[value8])); + if (value8 < exceptionIndexTable.length - 1) { + this.file.print(", "); + } + } + this.file.println(""); + } + } + } + + public void writeField(Field field) throws IOException { + MethodHTML methodHTML; + String text2 = Utility.getText2(field.getText2()); + String text = field.getText(); + String text3 = Utility.replace(Utility.getText2(field.getAccess_flags2()), " ", " "); + this.file.print( + "" + + text3 + + "\n" + + Class2HTML.createText(text2) + + "" + + text + + ""); + Attribute[] attributes = field.getAttributes(); + int value; + for (int value2 = value = 0; value2 < attributes.length; value2 = value) { + AttributeHTML attributeHTML = this.attribute_html; + Attribute attribute = attributes[value]; + StringBuilder stringBuilder = new StringBuilder().insert(0, text).append("@"); + int value3 = value; + value++; + attributeHTML.writeAttribute(attribute, stringBuilder.append(value3).toString()); + } + int value4; + int value5 = value4 = 0; + while (true) { + if (value5 >= attributes.length) { + methodHTML = this; + break; + } + if (attributes[value4].getTag() == 1) { + String text4 = ((ConstantValue) attributes[value4]).toString(); + PrintWriter printWriter = this.file; + StringBuilder stringBuilder2 = new StringBuilder().insert(0, "= ") + .append(text4) + .append("\n") + .toString()); + break; + } + value5 = ++value4; + } + methodHTML.file.println(""); + } + + public MethodHTML( + String text, + String class_name, + Method[] methods, + Field[] fields, + ConstantHTML constantHTML, + AttributeHTML attributeHTML) + throws IOException { + super(); + int value = 0; + this.class_name = class_name; + this.attribute_html = attributeHTML; + this.constant_html = constantHTML; + this.file = new PrintWriter(new FileOutputStream(("" + text + class_name + "_methods.html"))); + this.file.println(""); + this.file.println( + "Field name"); + for (int index = 0; value < fields.length; value = index) { + int value2 = index; + index++; + this.writeField(fields[value2]); + } + this.file.println("
Access flagsType
"); + this.file.println( + "Return typeArguments"); + int value3; + for (int value4 = value3 = 0; value4 < methods.length; value4 = value3) { + Method method = methods[value3]; + int value5 = value3; + value3++; + this.writeMethod(method, value5); + } + this.file.println("
Access flagsMethod name
"); + this.file.close(); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/util/Repository.java b/src/main/java/com/allatori/lib/bcel/util/Repository.java new file mode 100644 index 0000000..3e841e9 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/util/Repository.java @@ -0,0 +1,21 @@ +package com.allatori.lib.bcel.util; + +import com.allatori.lib.bcel.classfile.JavaClass; +import java.io.Serializable; + +public interface Repository extends Serializable { + + void processJavaClass(JavaClass javaClass); + + ClassPath getClassPath(); + + void clear(); + + JavaClass loadClass(Class classValue) throws ClassNotFoundException; + + JavaClass getJavaClass(String text); + + void processJavaClass2(JavaClass javaClass); + + JavaClass getJavaClass2(String text) throws ClassNotFoundException; +} diff --git a/src/main/java/com/allatori/lib/bcel/util/SyntheticRepository.java b/src/main/java/com/allatori/lib/bcel/util/SyntheticRepository.java new file mode 100644 index 0000000..d53ea31 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/util/SyntheticRepository.java @@ -0,0 +1,117 @@ +package com.allatori.lib.bcel.util; + +import com.allatori.lib.bcel.classfile.ClassParser; +import com.allatori.lib.bcel.classfile.JavaClass; +import java.io.IOException; +import java.io.InputStream; +import java.lang.ref.SoftReference; +import java.util.HashMap; +import java.util.Map; + +public class SyntheticRepository implements Repository { + + public static final String DEFAULT_PATH = ClassPath.getClassPath(); + + public Map _loadedClasses; + + public static Map _instances = new HashMap(); + + public ClassPath _path; + + @Override + public void processJavaClass2(JavaClass javaClass) { + this._loadedClasses.remove(javaClass.getText2()); + } + + @Override + public JavaClass getJavaClass(String text) { + SoftReference softReference; + return (softReference = (SoftReference) this._loadedClasses.get(text)) == null + ? null + : (JavaClass) softReference.get(); + } + + @Override + public JavaClass getJavaClass2(String text) throws ClassNotFoundException { + if (text != null && !text.equals("")) { + String text2 = text.replace('/', '.'); + JavaClass javaClass; + if ((javaClass = this.getJavaClass(text2)) != null) { + return javaClass; + } + try { + return this.loadClass(this._path.getInputStream2(text2), text2); + } catch (IOException oException) { + throw new ClassNotFoundException( + ("Exception while looking for class " + text2 + ": " + oException.toString())); + } + } else { + throw new IllegalArgumentException(("Invalid class name " + text)); + } + } + + public static SyntheticRepository getInstance(ClassPath classPath) { + SyntheticRepository syntheticRepository; + if ((syntheticRepository = (SyntheticRepository) _instances.get(classPath)) == null) { + syntheticRepository = new SyntheticRepository(classPath); + _instances.put(classPath, syntheticRepository); + } + return syntheticRepository; + } + + @Override + public JavaClass loadClass(Class classValue) throws ClassNotFoundException { + String name = classValue.getName(); + JavaClass javaClass; + if ((javaClass = this.getJavaClass(name)) != null) { + return javaClass; + } + String text = name; + int value; + if ((value = name.lastIndexOf(46)) > 0) { + text = text.substring(value + 1); + } + return this.loadClass(classValue.getResourceAsStream(text + ".class"), name); + } + + @Override + public void clear() { + this._loadedClasses.clear(); + } + + @Override + public ClassPath getClassPath() { + return this._path; + } + + @Override + public void processJavaClass(JavaClass javaClass) { + this._loadedClasses.put(javaClass.getText2(), new SoftReference<>(javaClass)); + javaClass.setRepository(this); + } + + public SyntheticRepository(ClassPath classPath) { + super(); + this._path = null; + this._loadedClasses = new HashMap(); + this._path = classPath; + } + + public static SyntheticRepository getInstance() { + return getInstance(ClassPath.SYSTEM_CLASS_PATH); + } + + public JavaClass loadClass(InputStream inputStream, String text) throws ClassNotFoundException { + try { + if (inputStream != null) { + JavaClass javaClass = new ClassParser(inputStream, text).parse(); + this.processJavaClass(javaClass); + return javaClass; + } + } catch (IOException oException) { + throw new ClassNotFoundException( + ("Exception while looking for class " + text + ": " + oException.toString())); + } + throw new ClassNotFoundException(("SyntheticRepository could not load " + text)); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/util/TypeParserThreadLocal.java b/src/main/java/com/allatori/lib/bcel/util/TypeParserThreadLocal.java new file mode 100644 index 0000000..6266b40 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/util/TypeParserThreadLocal.java @@ -0,0 +1,9 @@ +package com.allatori.lib.bcel.util; + +public class TypeParserThreadLocal extends ThreadLocal { + + @Override + public Object initialValue() { + return new Integer(0); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/util/TypeParserThreadLocal2.java b/src/main/java/com/allatori/lib/bcel/util/TypeParserThreadLocal2.java new file mode 100644 index 0000000..c603d74 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/util/TypeParserThreadLocal2.java @@ -0,0 +1,9 @@ +package com.allatori.lib.bcel.util; + +public class TypeParserThreadLocal2 extends ThreadLocal { + + @Override + public Object initialValue() { + return new Integer(0); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/util/comparator/ClassGenComparator.java b/src/main/java/com/allatori/lib/bcel/util/comparator/ClassGenComparator.java new file mode 100644 index 0000000..795505c --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/util/comparator/ClassGenComparator.java @@ -0,0 +1,19 @@ +package com.allatori.lib.bcel.util.comparator; + +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.lib.bcel.util.BCELComparator; + +public class ClassGenComparator implements BCELComparator { + + @Override + public int hashCode(Object result) { + return ((ClassGen) result).getClassName().hashCode(); + } + + @Override + public boolean equals(Object result, Object result2) { + ClassGen classGen = (ClassGen) result; + ClassGen classGen2 = (ClassGen) result2; + return classGen.getClassName().equals(classGen2.getClassName()); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/util/comparator/ConstantComparator.java b/src/main/java/com/allatori/lib/bcel/util/comparator/ConstantComparator.java new file mode 100644 index 0000000..d0f0c49 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/util/comparator/ConstantComparator.java @@ -0,0 +1,19 @@ +package com.allatori.lib.bcel.util.comparator; + +import com.allatori.lib.bcel.classfile.Constant; +import com.allatori.lib.bcel.util.BCELComparator; + +public class ConstantComparator implements BCELComparator { + + @Override + public boolean equals(Object result, Object result2) { + Constant constant = (Constant) result; + Constant constant2 = (Constant) result2; + return constant.toString().equals(constant2.toString()); + } + + @Override + public int hashCode(Object result) { + return ((Constant) result).toString().hashCode(); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/util/comparator/FieldComparator.java b/src/main/java/com/allatori/lib/bcel/util/comparator/FieldComparator.java new file mode 100644 index 0000000..d2c9741 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/util/comparator/FieldComparator.java @@ -0,0 +1,20 @@ +package com.allatori.lib.bcel.util.comparator; + +import com.allatori.lib.bcel.classfile.Field; +import com.allatori.lib.bcel.util.BCELComparator; + +public class FieldComparator implements BCELComparator { + + @Override + public boolean equals(Object result, Object result2) { + Field field = (Field) result; + Field field2 = (Field) result2; + return field.getText().equals(field2.getText()) && field.getText2().equals(field2.getText2()); + } + + @Override + public int hashCode(Object result) { + Field field; + return (field = (Field) result).getText2().hashCode() ^ field.getText().hashCode(); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/util/comparator/FieldGenComparator.java b/src/main/java/com/allatori/lib/bcel/util/comparator/FieldGenComparator.java new file mode 100644 index 0000000..fdfe96e --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/util/comparator/FieldGenComparator.java @@ -0,0 +1,21 @@ +package com.allatori.lib.bcel.util.comparator; + +import com.allatori.lib.bcel.generic.FieldGen; +import com.allatori.lib.bcel.util.BCELComparator; + +public class FieldGenComparator implements BCELComparator { + + @Override + public boolean equals(Object result, Object result2) { + FieldGen fieldGen = (FieldGen) result; + FieldGen fieldGen2 = (FieldGen) result2; + return fieldGen.getName().equals(fieldGen2.getName()) + && fieldGen.getText().equals(fieldGen2.getText()); + } + + @Override + public int hashCode(Object result) { + FieldGen fieldGen; + return (fieldGen = (FieldGen) result).getText().hashCode() ^ fieldGen.getName().hashCode(); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/util/comparator/JavaClassComparator.java b/src/main/java/com/allatori/lib/bcel/util/comparator/JavaClassComparator.java new file mode 100644 index 0000000..aa6b58d --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/util/comparator/JavaClassComparator.java @@ -0,0 +1,19 @@ +package com.allatori.lib.bcel.util.comparator; + +import com.allatori.lib.bcel.classfile.JavaClass; +import com.allatori.lib.bcel.util.BCELComparator; + +public class JavaClassComparator implements BCELComparator { + + @Override + public boolean equals(Object result, Object result2) { + JavaClass javaClass = (JavaClass) result; + JavaClass javaClass2 = (JavaClass) result2; + return javaClass.getText2().equals(javaClass2.getText2()); + } + + @Override + public int hashCode(Object result) { + return ((JavaClass) result).getText2().hashCode(); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/util/comparator/MethodComparator.java b/src/main/java/com/allatori/lib/bcel/util/comparator/MethodComparator.java new file mode 100644 index 0000000..124f924 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/util/comparator/MethodComparator.java @@ -0,0 +1,27 @@ +package com.allatori.lib.bcel.util.comparator; + +import com.allatori.lib.bcel.classfile.Method; +import com.allatori.lib.bcel.util.BCELComparator; + +public class MethodComparator implements BCELComparator { + + public static MethodComparator methodComparator = new MethodComparator(); + + @Override + public boolean equals(Object result, Object result2) { + Method method = (Method) result; + Method method2 = (Method) result2; + return method.getText().equals(method2.getText()) + && method.getText2().equals(method2.getText2()); + } + + @Override + public int hashCode(Object result) { + Method method; + return (method = (Method) result).getText2().hashCode() ^ method.getText().hashCode(); + } + + public static MethodComparator getMethodComparator() { + return methodComparator; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/util/comparator/MethodComparator2.java b/src/main/java/com/allatori/lib/bcel/util/comparator/MethodComparator2.java new file mode 100644 index 0000000..5ee4129 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/util/comparator/MethodComparator2.java @@ -0,0 +1,21 @@ +package com.allatori.lib.bcel.util.comparator; + +import com.allatori.lib.bcel.classfile.Method; +import com.allatori.lib.bcel.util.BCELComparator; + +public class MethodComparator2 implements BCELComparator { + + @Override + public boolean equals(Object result, Object result2) { + Method method = (Method) result; + Method method2 = (Method) result2; + return method.getText().equals(method2.getText()) + && method.getText2().equals(method2.getText2()); + } + + @Override + public int hashCode(Object result) { + Method method; + return (method = (Method) result).getText2().hashCode() ^ method.getText().hashCode(); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/util/comparator/MethodGenComparator.java b/src/main/java/com/allatori/lib/bcel/util/comparator/MethodGenComparator.java new file mode 100644 index 0000000..c415454 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/util/comparator/MethodGenComparator.java @@ -0,0 +1,21 @@ +package com.allatori.lib.bcel.util.comparator; + +import com.allatori.lib.bcel.generic.MethodGen; +import com.allatori.lib.bcel.util.BCELComparator; + +public class MethodGenComparator implements BCELComparator { + + @Override + public int hashCode(Object result) { + MethodGen methodGen; + return (methodGen = (MethodGen) result).getText().hashCode() ^ methodGen.getName().hashCode(); + } + + @Override + public boolean equals(Object result, Object result2) { + MethodGen methodGen = (MethodGen) result; + MethodGen methodGen2 = (MethodGen) result2; + return methodGen.getName().equals(methodGen2.getName()) + && methodGen.getText().equals(methodGen2.getText()); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/GraphicalVerifier.java b/src/main/java/com/allatori/lib/bcel/verifier/GraphicalVerifier.java new file mode 100644 index 0000000..c3bea3c --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/GraphicalVerifier.java @@ -0,0 +1,43 @@ +package com.allatori.lib.bcel.verifier; + +import com.allatori.lib.bcel.generic.Type; +import java.awt.Dimension; +import java.awt.Toolkit; +import javax.swing.UIManager; + +public class GraphicalVerifier { + + public boolean packFrame = false; + + public GraphicalVerifier() { + VerifierAppFrame verifierAppFrame = new VerifierAppFrame(); + if (this.packFrame) { + verifierAppFrame.pack(); + } else { + verifierAppFrame.validate(); + } + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + Dimension dimension; + if ((dimension = verifierAppFrame.getSize()).height > screenSize.height) { + dimension.height = screenSize.height; + } + if (dimension.width > screenSize.width) { + dimension.width = screenSize.width; + } + verifierAppFrame.setLocation( + (screenSize.width - dimension.width) / 2, (screenSize.height - dimension.height) / 2); + verifierAppFrame.setVisible(true); + verifierAppFrame.classNamesJList.setModel(new VerifierFactoryListModel()); + VerifierFactory.getVerifier(Type.OBJECT.getClassName()); + verifierAppFrame.classNamesJList.setSelectedIndex(0); + } + + public static void main(String[] texts) { + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } catch (Exception exception) { + exception.printStackTrace(); + } + new GraphicalVerifier(); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/NativeVerifier.java b/src/main/java/com/allatori/lib/bcel/verifier/NativeVerifier.java new file mode 100644 index 0000000..fa287ff --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/NativeVerifier.java @@ -0,0 +1,36 @@ +package com.allatori.lib.bcel.verifier; + +public abstract class NativeVerifier { + + public static void main(String[] texts) { + if (texts.length != 1) { + System.out.println("Verifier front-end: need exactly one argument."); + System.exit(1); + } + int value; + if ((value = texts[0].lastIndexOf(".class")) != -1) { + texts[0] = texts[0].substring(0, value); + } + texts[0] = texts[0].replace('/', '.'); + try { + Class.forName(texts[0]); + } catch (ExceptionInInitializerError exceptionInInitializerError) { + System.out.println( + "NativeVerifier: ExceptionInInitializerError encountered on '" + texts[0] + "'."); + System.out.println(exceptionInInitializerError); + System.exit(1); + } catch (LinkageError linkageError) { + System.out.println("NativeVerifier: LinkageError encountered on '" + texts[0] + "'."); + System.out.println(linkageError); + System.exit(1); + } catch (ClassNotFoundException classNotFoundException) { + System.out.println("NativeVerifier: FILE NOT FOUND: '" + texts[0] + "'."); + System.exit(1); + } catch (Throwable throwable) { + System.out.println("NativeVerifier: Unspecified verification error on'" + texts[0] + "'."); + System.exit(1); + } + System.out.println("NativeVerifier: Class file '" + texts[0] + "' seems to be okay."); + System.exit(0); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/PassVerifier.java b/src/main/java/com/allatori/lib/bcel/verifier/PassVerifier.java new file mode 100644 index 0000000..bb87cd8 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/PassVerifier.java @@ -0,0 +1,33 @@ +package com.allatori.lib.bcel.verifier; + +import java.util.ArrayList; +import java.util.List; + +public abstract class PassVerifier { + + public VerificationResult verificationResult; + + public List messages = new ArrayList(); + + public void addMessage(String text) { + this.messages.add(text); + } + + public abstract VerificationResult getVerificationResult(); + + public String[] getMessages() { + this.getVerificationResult2(); + return (String[]) this.messages.toArray(new String[this.messages.size()]); + } + + public VerificationResult getVerificationResult2() { + if (this.verificationResult == null) { + this.verificationResult = this.getVerificationResult(); + } + return this.verificationResult; + } + + public PassVerifier() { + this.verificationResult = null; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/TransitiveHull.java b/src/main/java/com/allatori/lib/bcel/verifier/TransitiveHull.java new file mode 100644 index 0000000..0427285 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/TransitiveHull.java @@ -0,0 +1,87 @@ +package com.allatori.lib.bcel.verifier; + +import com.allatori.lib.bcel.Repository; +import com.allatori.lib.bcel.classfile.JavaClass; +import java.io.PrintStream; + +public class TransitiveHull implements VerifierFactoryObserver { + + public int indent = 0; + + public static void main(String[] texts) { + if (texts.length != 1) { + System.out.println("Need exactly one argument: The root class to verify."); + System.exit(1); + } + int value; + if ((value = texts[0].lastIndexOf(".class")) != -1) { + texts[0] = texts[0].substring(0, value); + } + texts[0] = texts[0].replace('/', '.'); + TransitiveHull transitiveHull = new TransitiveHull(); + VerifierFactory.attach(transitiveHull); + VerifierFactory.getVerifier(texts[0]); + VerifierFactory.detach(transitiveHull); + } + + @Override + public void update(String text) { + System.gc(); + int value; + for (int value2 = value = 0; value2 < this.indent; value2 = value) { + PrintStream printStream = System.out; + value++; + printStream.print(" "); + } + System.out.println(text); + this.indent++; + Verifier verifier; + VerificationResult verificationResult; + if ((verificationResult = + (verifier = VerifierFactory.getVerifier(text)).createVerificationResult()) + != VerificationResult.VERIFICATION_RESULT2) { + System.out.println("Pass 1:\n" + verificationResult); + } + VerificationResult verificationResult2; + if ((verificationResult2 = verifier.createVerificationResult2()) + != VerificationResult.VERIFICATION_RESULT2) { + System.out.println("Pass 2:\n" + verificationResult2); + } + if (verificationResult2 == VerificationResult.VERIFICATION_RESULT2) { + try { + JavaClass javaClass = Repository.lookupClass(verifier.getClassName()); + for (int index = 0; index < javaClass.getMethods().length; index++) { + VerificationResult verificationResult3; + if ((verificationResult3 = verifier.doPass3a(index)) + != VerificationResult.VERIFICATION_RESULT2) { + System.out.println( + "" + + verifier.getClassName() + + ", Pass 3a, method " + + index + + " ['" + + javaClass.getMethods()[index] + + "']:\n" + + verificationResult3); + } + VerificationResult verificationResult4; + if ((verificationResult4 = verifier.doPass3b(index)) + != VerificationResult.VERIFICATION_RESULT2) { + System.out.println( + "" + + verifier.getClassName() + + ", Pass 3b, method " + + index + + " ['" + + javaClass.getMethods()[index] + + "']:\n" + + verificationResult4); + } + } + } catch (ClassNotFoundException classNotFoundException) { + System.err.println("Could not find class " + verifier.getClassName() + " in Repository"); + } + } + this.indent--; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/VerificationResult.java b/src/main/java/com/allatori/lib/bcel/verifier/VerificationResult.java new file mode 100644 index 0000000..2afb757 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/VerificationResult.java @@ -0,0 +1,52 @@ +package com.allatori.lib.bcel.verifier; + +public class VerificationResult { + + public String detailMessage; + + public static final String TEXT = "Not yet verified."; + + public static final int VERIFIED_NOTYET = 0; + + public static final String TEXT2 = "Passed verification."; + + public static final VerificationResult VERIFICATION_RESULT = + new VerificationResult(0, "Not yet verified."); + + public static final int VERIFIED_REJECTED = 2; + + public static final VerificationResult VERIFICATION_RESULT2 = + new VerificationResult(1, "Passed verification."); + + public int numeric; + + public static final int VERIFIED_OK = 1; + + public VerificationResult(int numeric, String detailMessage) { + super(); + this.numeric = numeric; + this.detailMessage = detailMessage; + } + + @Override + public boolean equals(Object result) { + VerificationResult verificationResult; + return !(result instanceof VerificationResult) + ? false + : (verificationResult = (VerificationResult) result).numeric == this.numeric + && verificationResult.detailMessage.equals(this.detailMessage); + } + + @Override + public int hashCode() { + return this.numeric ^ this.detailMessage.hashCode(); + } + + public int getStatus() { + return this.numeric; + } + + public String getDetailMessage() { + return this.detailMessage; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/Verifier.java b/src/main/java/com/allatori/lib/bcel/verifier/Verifier.java new file mode 100644 index 0000000..43f42fc --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/Verifier.java @@ -0,0 +1,216 @@ +package com.allatori.lib.bcel.verifier; + +import com.allatori.lib.bcel.Repository; +import com.allatori.lib.bcel.classfile.JavaClass; +import com.allatori.lib.bcel.verifier.statics.Pass1Verifier; +import com.allatori.lib.bcel.verifier.statics.Pass2Verifier; +import com.allatori.lib.bcel.verifier.statics.Pass3aVerifier; +import com.allatori.lib.bcel.verifier.structurals.Pass3bVerifier; +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +public class Verifier { + + public final String classname; + + public Map p3avs; + + public Pass2Verifier p2v; + + public Map p3bvs; + + public Pass1Verifier p1v; + + public void flush() { + this.p1v = null; + this.p2v = null; + this.p3avs.clear(); + this.p3bvs.clear(); + } + + public final String getClassName() { + return this.classname; + } + + public VerificationResult createVerificationResult() { + if (this.p1v == null) { + this.p1v = new Pass1Verifier(this); + } + return this.p1v.getVerificationResult2(); + } + + public static void main(String[] texts) { + System.out.println( + "JustIce by Enver Haase, (C) 2001-2002.\n" + + "\n" + + "\n"); + int value; + for (int value2 = value = 0; value2 < texts.length; value2 = ++value) { + try { + int value3; + if (texts[value].endsWith(".class") + && (value3 = texts[value].lastIndexOf(".class")) != -1) { + texts[value] = texts[value].substring(0, value3); + } + texts[value] = texts[value].replace('/', '.'); + System.out.println("Now verifying: " + texts[value] + "\n"); + Verifier verifier; + Verifier verifier2 = verifier = VerifierFactory.getVerifier(texts[value]); + VerificationResult verificationResult = verifier2.createVerificationResult(); + System.out.println("Pass 1:\n" + verificationResult); + VerificationResult verificationResult2 = verifier2.createVerificationResult2(); + System.out.println("Pass 2:\n" + verificationResult2); + if (verificationResult2 == VerificationResult.VERIFICATION_RESULT2) { + JavaClass javaClass = Repository.lookupClass(texts[value]); + int value4; + for (int value5 = value4 = 0; value5 < javaClass.getMethods().length; value5 = value4) { + VerificationResult verificationResult3 = verifier.doPass3a(value4); + System.out.println( + "Pass 3a, method number " + + value4 + + " ['" + + javaClass.getMethods()[value4] + + "']:\n" + + verificationResult3); + VerificationResult verificationResult4 = verifier.doPass3b(value4); + PrintStream printStream = System.out; + StringBuilder stringBuilder = + new StringBuilder() + .insert(0, "Pass 3b, method number ") + .append(value4) + .append(" ['") + .append(javaClass.getMethods()[value4]) + .append("']:\n"); + value4++; + printStream.println(stringBuilder.append(verificationResult4).toString()); + } + } + System.out.println("Warnings:"); + String[] texts2; + if ((texts2 = verifier.getMessages()).length == 0) { + System.out.println(""); + } + int value6; + for (int value7 = value6 = 0; value7 < texts2.length; value7 = value6) { + int value8 = value6; + String[] texts3 = texts2; + PrintStream printStream2 = System.out; + value6++; + printStream2.println(texts3[value8]); + } + System.out.println("\n"); + verifier.flush(); + Repository.clearCache(); + System.gc(); + } catch (ClassNotFoundException classNotFoundException) { + classNotFoundException.printStackTrace(); + } + } + } + + public VerificationResult createVerificationResult2() { + if (this.p2v == null) { + this.p2v = new Pass2Verifier(this); + } + return this.p2v.getVerificationResult2(); + } + + public String[] getMessages() throws ClassNotFoundException { + ArrayList values2 = new ArrayList(); + if (this.p1v != null) { + String[] messages = this.p1v.getMessages(); + int value; + for (int value2 = value = 0; value2 < messages.length; value2 = value) { + StringBuilder stringBuilder = new StringBuilder().append("Pass 1: "); + String text = messages[value]; + value++; + values2.add(stringBuilder.append(text).toString()); + } + } + if (this.p2v != null) { + String[] messages2 = this.p2v.getMessages(); + int value3; + for (int value4 = value3 = 0; value4 < messages2.length; value4 = value3) { + StringBuilder stringBuilder2 = new StringBuilder().insert(0, "Pass 2: "); + String text2 = messages2[value3]; + value3++; + values2.add(stringBuilder2.append(text2).toString()); + } + } + for (Pass3aVerifier pass3aVerifier : + ((Iterable) ((Iterable) this.p3avs.values()))) { + String[] messages3 = pass3aVerifier.getMessages(); + int methodNo = pass3aVerifier.getMethodNo(); + int value5; + for (int value6 = value5 = 0; value6 < messages3.length; value6 = value5) { + StringBuilder stringBuilder3 = + new StringBuilder() + .insert(0, "Pass 3a, method ") + .append(methodNo) + .append(" ('") + .append(Repository.lookupClass(this.classname).getMethods()[methodNo]) + .append("'): "); + String text3 = messages3[value5]; + value5++; + values2.add(stringBuilder3.append(text3).toString()); + } + } + for (Pass3bVerifier pass3bVerifier : + ((Iterable) ((Iterable) this.p3bvs.values()))) { + String[] messages4 = pass3bVerifier.getMessages(); + int methodNo2 = pass3bVerifier.getMethodNo(); + int value7; + for (int value8 = value7 = 0; value8 < messages4.length; value8 = value7) { + StringBuilder stringBuilder4 = + new StringBuilder() + .insert(0, "Pass 3b, method ") + .append(methodNo2) + .append(" ('") + .append(Repository.lookupClass(this.classname).getMethods()[methodNo2]) + .append("'): "); + String text4 = messages4[value7]; + value7++; + values2.add(stringBuilder4.append(text4).toString()); + } + } + String[] texts = new String[values2.size()]; + int value9; + for (int value10 = value9 = 0; value10 < values2.size(); value10 = value9) { + String text5 = (String) values2.get(value9); + int value11 = value9; + value9++; + texts[value11] = text5; + } + return texts; + } + + public VerificationResult doPass3a(int value) { + String text = Integer.toString(value); + Pass3aVerifier pass3aVerifier = (Pass3aVerifier) this.p3avs.get(text); + if (this.p3avs.get(text) == null) { + pass3aVerifier = new Pass3aVerifier(this, value); + this.p3avs.put(text, pass3aVerifier); + } + return pass3aVerifier.getVerificationResult2(); + } + + public Verifier(String classname) { + super(); + this.p3avs = new HashMap(); + this.p3bvs = new HashMap(); + this.classname = classname; + this.flush(); + } + + public VerificationResult doPass3b(int value) { + String text = Integer.toString(value); + Pass3bVerifier pass3bVerifier = (Pass3bVerifier) this.p3bvs.get(text); + if (this.p3bvs.get(text) == null) { + pass3bVerifier = new Pass3bVerifier(this, value); + this.p3bvs.put(text, pass3bVerifier); + } + return pass3bVerifier.getVerificationResult2(); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/VerifierAppFrame.java b/src/main/java/com/allatori/lib/bcel/verifier/VerifierAppFrame.java new file mode 100644 index 0000000..1f03f68 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/VerifierAppFrame.java @@ -0,0 +1,440 @@ +package com.allatori.lib.bcel.verifier; + +import com.allatori.lib.bcel.Repository; +import com.allatori.lib.bcel.classfile.JavaClass; +import com.allatori.lib.bcel.verifier.ui.VerifierActionListener; +import com.allatori.lib.bcel.verifier.ui.VerifierActionListener2; +import com.allatori.lib.bcel.verifier.ui.VerifierActionListener3; +import com.allatori.lib.bcel.verifier.ui.VerifierSelectionListener; +import com.allatori.lib.bcel.verifier.ui.VerifierSelectionListener2; +import com.allatori.lib.bcel.verifier.ui.VerifierSelectionListener3; +import java.awt.CardLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.WindowEvent; +import javax.swing.BorderFactory; +import javax.swing.JFrame; +import javax.swing.JList; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JSplitPane; +import javax.swing.JTextPane; +import javax.swing.KeyStroke; +import javax.swing.event.ListSelectionEvent; + +public class VerifierAppFrame extends JFrame { + + public JScrollPane jScrollPane6; + + public JMenu jMenu1; + + public JTextPane messagesTextPane; + + public JScrollPane jScrollPane3; + + public JPanel jPanel; + + public JMenuItem aboutMenuItem; + + public String text; + + public JTextPane pass3aTextPane; + + public JScrollPane jScrollPane5; + + public JMenuItem newFileMenuItem; + + public JPanel jPanel3; + + public JScrollPane jScrollPane7; + + public JPanel jPanel2; + + public JScrollPane jScrollPane1; + + public CardLayout cardLayout1; + + public JList pass3aJList; + + public JPanel messagesPanel; + + public JScrollPane jScrollPane2; + + public JTextPane pass3bTextPane; + + public GridLayout gridLayout4; + + public JScrollPane messagesScrollPane; + + public JTextPane pass2TextPane; + + public GridLayout gridLayout1; + + public JPanel jPanel1; + + public JList classNamesJList; + + public JMenuBar jMenuBar1; + + public GridLayout gridLayout3; + + public JTextPane pass1TextPane; + + public JSplitPane jSplitPane1; + + public GridLayout gridLayout2; + + public String JUSTICE_VERSION; + + public JMenu jMenu2; + + public JMenuItem whatisMenuItem; + + public JSplitPane jSplitPane3; + + public JSplitPane jSplitPane2; + + public JList pass3bJList; + + public JSplitPane jSplitPane4; + + public JScrollPane jScrollPane4; + + public synchronized void pass3bJList_valueChanged(ListSelectionEvent listSelectionEvent) { + if (!listSelectionEvent.getValueIsAdjusting()) { + Verifier verifier = VerifierFactory.getVerifier(this.text); + String text2 = ""; + byte value = 1; + byte value2 = 0; + int value3; + for (int value4 = value3 = 0; + value4 < this.pass3bJList.getModel().getSize(); + value4 = ++value3) { + if (this.pass3bJList.isSelectedIndex(value3)) { + VerificationResult verificationResult; + if ((verificationResult = verifier.doPass3b(value3)).getStatus() == 2) { + value = 0; + value2 = 1; + } + try { + JavaClass javaClass = Repository.lookupClass(verifier.getClassName()); + text2 = + "" + + text2 + + "Method '" + + javaClass.getMethods()[value3] + + "': " + + verificationResult.getDetailMessage().replace('\n', ' ') + + "\n\n"; + } catch (ClassNotFoundException classNotFoundException) { + classNotFoundException.printStackTrace(); + } + } + } + this.pass3bTextPane.setText(text2); + this.pass3bTextPane.setBackground( + value != 0 ? Color.green : (value2 != 0 ? Color.red : Color.yellow)); + } + } + + public synchronized void classNamesJList_valueChanged(ListSelectionEvent listSelectionEvent) { + if (!listSelectionEvent.getValueIsAdjusting()) { + this.text = this.classNamesJList.getSelectedValue().toString(); + VerifierAppFrame verifierAppFrame; + label15: + { + try { + this.verify(); + } catch (ClassNotFoundException classNotFoundException) { + verifierAppFrame = this; + classNotFoundException.printStackTrace(); + break label15; + } + verifierAppFrame = this; + } + verifierAppFrame.classNamesJList.setSelectedValue(this.text, true); + } + } + + public synchronized void pass3aJList_valueChanged(ListSelectionEvent listSelectionEvent) { + if (!listSelectionEvent.getValueIsAdjusting()) { + Verifier verifier = VerifierFactory.getVerifier(this.text); + String text2 = ""; + byte value = 1; + byte value2 = 0; + int value3; + for (int value4 = value3 = 0; + value4 < this.pass3aJList.getModel().getSize(); + value4 = ++value3) { + if (this.pass3aJList.isSelectedIndex(value3)) { + VerificationResult verificationResult; + if ((verificationResult = verifier.doPass3a(value3)).getStatus() == 2) { + value = 0; + value2 = 1; + } + try { + JavaClass javaClass = Repository.lookupClass(verifier.getClassName()); + text2 = + "" + + text2 + + "Method '" + + javaClass.getMethods()[value3] + + "': " + + verificationResult.getDetailMessage().replace('\n', ' ') + + "\n\n"; + } catch (ClassNotFoundException classNotFoundException) { + classNotFoundException.printStackTrace(); + } + } + } + this.pass3aTextPane.setText(text2); + this.pass3aTextPane.setBackground( + value != 0 ? Color.green : (value2 != 0 ? Color.red : Color.yellow)); + } + } + + public void whatisMenuItem_actionPerformed(ActionEvent actionEvent) { + JOptionPane.showMessageDialog( + this, + "The upper four boxes to the right reflect verification passes according to The Java" + + " Virtual Machine Specification.\n" + + "These are (in that order): Pass one, Pass two, Pass three (before data flow" + + " analysis), Pass three (data flow analysis).\n" + + "The bottom box to the right shows (warning) messages; warnings do not cause a class" + + " to be rejected.", + this.JUSTICE_VERSION, + 1); + } + + public void jbInit() throws Exception { + this.jPanel = (JPanel) this.getContentPane(); + this.jPanel.setLayout(this.cardLayout1); + this.setJMenuBar(this.jMenuBar1); + this.setSize(new Dimension(708, 451)); + this.setTitle("JustIce"); + this.jPanel1.setMinimumSize(new Dimension(100, 100)); + this.jPanel1.setPreferredSize(new Dimension(100, 100)); + this.jPanel1.setLayout(this.gridLayout1); + this.jSplitPane2.setOrientation(0); + this.jPanel2.setLayout(this.gridLayout2); + this.jPanel3.setMinimumSize(new Dimension(200, 100)); + this.jPanel3.setPreferredSize(new Dimension(400, 400)); + this.jPanel3.setLayout(this.gridLayout4); + this.messagesPanel.setMinimumSize(new Dimension(100, 100)); + this.messagesPanel.setLayout(this.gridLayout3); + this.jPanel2.setMinimumSize(new Dimension(200, 100)); + this.jMenu1.setText("File"); + this.jScrollPane1.getViewport().setBackground(Color.red); + this.messagesScrollPane.getViewport().setBackground(Color.red); + this.messagesScrollPane.setPreferredSize(new Dimension(10, 10)); + this.classNamesJList.addListSelectionListener(new VerifierSelectionListener3(this)); + this.classNamesJList.setSelectionMode(0); + this.jScrollPane3.setBorder(BorderFactory.createLineBorder(Color.black)); + this.jScrollPane3.setPreferredSize(new Dimension(100, 100)); + this.gridLayout4.setRows(4); + this.gridLayout4.setColumns(1); + this.gridLayout4.setHgap(1); + this.jScrollPane4.setBorder(BorderFactory.createLineBorder(Color.black)); + this.jScrollPane4.setPreferredSize(new Dimension(100, 100)); + this.pass1TextPane.setBorder(BorderFactory.createRaisedBevelBorder()); + this.pass1TextPane.setToolTipText(""); + this.pass1TextPane.setEditable(false); + this.pass2TextPane.setBorder(BorderFactory.createRaisedBevelBorder()); + this.pass2TextPane.setEditable(false); + this.messagesTextPane.setBorder(BorderFactory.createRaisedBevelBorder()); + this.messagesTextPane.setEditable(false); + this.newFileMenuItem.setText("New..."); + this.newFileMenuItem.setAccelerator(KeyStroke.getKeyStroke(78, 2, true)); + this.newFileMenuItem.addActionListener(new VerifierActionListener3(this)); + this.pass3aTextPane.setEditable(false); + this.pass3bTextPane.setEditable(false); + this.pass3aJList.addListSelectionListener(new VerifierSelectionListener2(this)); + this.pass3bJList.addListSelectionListener(new VerifierSelectionListener(this)); + this.jMenu2.setText("Help"); + this.whatisMenuItem.setText("What is..."); + this.whatisMenuItem.addActionListener(new VerifierActionListener2(this)); + this.aboutMenuItem.setText("About"); + this.aboutMenuItem.addActionListener(new VerifierActionListener(this)); + this.jSplitPane2.add(this.messagesPanel, "bottom"); + this.messagesPanel.add(this.messagesScrollPane, null); + this.messagesScrollPane.getViewport().add(this.messagesTextPane, null); + this.jSplitPane2.add(this.jPanel3, "top"); + this.jPanel3.add(this.jScrollPane3, null); + this.jScrollPane3.getViewport().add(this.pass1TextPane, null); + this.jPanel3.add(this.jScrollPane4, null); + this.jPanel3.add(this.jSplitPane3, null); + this.jSplitPane3.add(this.jScrollPane2, "left"); + this.jScrollPane2.getViewport().add(this.pass3aJList, null); + this.jSplitPane3.add(this.jScrollPane5, "right"); + this.jScrollPane5.getViewport().add(this.pass3aTextPane, null); + this.jPanel3.add(this.jSplitPane4, null); + this.jSplitPane4.add(this.jScrollPane6, "left"); + this.jScrollPane6.getViewport().add(this.pass3bJList, null); + this.jSplitPane4.add(this.jScrollPane7, "right"); + this.jScrollPane7.getViewport().add(this.pass3bTextPane, null); + this.jScrollPane4.getViewport().add(this.pass2TextPane, null); + this.jSplitPane1.add(this.jPanel2, "top"); + this.jPanel2.add(this.jScrollPane1, null); + this.jSplitPane1.add(this.jPanel1, "bottom"); + this.jPanel1.add(this.jSplitPane2, null); + this.jScrollPane1.getViewport().add(this.classNamesJList, null); + this.jMenuBar1.add(this.jMenu1); + this.jMenuBar1.add(this.jMenu2); + this.jPanel.add(this.jSplitPane1, "jSplitPane1"); + this.jMenu1.add(this.newFileMenuItem); + this.jMenu2.add(this.whatisMenuItem); + this.jMenu2.add(this.aboutMenuItem); + this.jSplitPane2.setDividerLocation(300); + this.jSplitPane3.setDividerLocation(150); + this.jSplitPane4.setDividerLocation(150); + } + + public VerifierAppFrame() { + super(); + this.jSplitPane1 = new JSplitPane(); + this.jPanel1 = new JPanel(); + this.jPanel2 = new JPanel(); + this.jSplitPane2 = new JSplitPane(); + this.jPanel3 = new JPanel(); + this.classNamesJList = new JList(); + this.gridLayout1 = new GridLayout(); + this.messagesPanel = new JPanel(); + this.gridLayout2 = new GridLayout(); + this.jMenuBar1 = new JMenuBar(); + this.jMenu1 = new JMenu(); + this.jScrollPane1 = new JScrollPane(); + this.messagesScrollPane = new JScrollPane(); + this.jScrollPane3 = new JScrollPane(); + this.gridLayout4 = new GridLayout(); + this.jScrollPane4 = new JScrollPane(); + this.cardLayout1 = new CardLayout(); + this.JUSTICE_VERSION = "JustIce by Enver Haase"; + this.gridLayout3 = new GridLayout(); + this.pass1TextPane = new JTextPane(); + this.pass2TextPane = new JTextPane(); + this.messagesTextPane = new JTextPane(); + this.newFileMenuItem = new JMenuItem(); + this.jSplitPane3 = new JSplitPane(); + this.jSplitPane4 = new JSplitPane(); + this.jScrollPane2 = new JScrollPane(); + this.jScrollPane5 = new JScrollPane(); + this.jScrollPane6 = new JScrollPane(); + this.jScrollPane7 = new JScrollPane(); + this.pass3aJList = new JList(); + this.pass3bJList = new JList(); + this.pass3aTextPane = new JTextPane(); + this.pass3bTextPane = new JTextPane(); + this.jMenu2 = new JMenu(); + this.whatisMenuItem = new JMenuItem(); + this.aboutMenuItem = new JMenuItem(); + this.enableEvents(64L); + try { + this.jbInit(); + } catch (Exception exception) { + exception.printStackTrace(); + } + } + + @Override + public void processWindowEvent(WindowEvent windowEvent) { + super.processWindowEvent(windowEvent); + if (windowEvent.getID() == 201) { + System.exit(0); + } + } + + public void verify() throws ClassNotFoundException { + this.setTitle("PLEASE WAIT"); + Verifier verifier; + Verifier verifier2 = verifier = VerifierFactory.getVerifier(this.text); + verifier2.flush(); + VerificationResult verificationResult; + if ((verificationResult = verifier2.createVerificationResult()).getStatus() == 2) { + this.pass1TextPane.setText(verificationResult.getDetailMessage()); + this.pass1TextPane.setBackground(Color.red); + this.pass2TextPane.setText(""); + this.pass2TextPane.setBackground(Color.yellow); + this.pass3aTextPane.setText(""); + this.pass3aJList.setListData(new Object[0]); + this.pass3aTextPane.setBackground(Color.yellow); + this.pass3bTextPane.setText(""); + this.pass3bJList.setListData(new Object[0]); + verifier2 = verifier; + this.pass3bTextPane.setBackground(Color.yellow); + } else { + this.pass1TextPane.setBackground(Color.green); + this.pass1TextPane.setText(verificationResult.getDetailMessage()); + VerificationResult verificationResult2; + if ((verificationResult2 = verifier.createVerificationResult2()).getStatus() == 2) { + this.pass2TextPane.setText(verificationResult2.getDetailMessage()); + this.pass2TextPane.setBackground(Color.red); + this.pass3aTextPane.setText(""); + this.pass3aTextPane.setBackground(Color.yellow); + this.pass3aJList.setListData(new Object[0]); + this.pass3bTextPane.setText(""); + this.pass3bTextPane.setBackground(Color.yellow); + this.pass3bJList.setListData(new Object[0]); + verifier2 = verifier; + } else { + this.pass2TextPane.setText(verificationResult2.getDetailMessage()); + this.pass2TextPane.setBackground(Color.green); + JavaClass javaClass; + String[] texts = + new String[(javaClass = Repository.lookupClass(this.text)).getMethods().length]; + int value; + for (int value2 = value = 0; value2 < javaClass.getMethods().length; value2 = value) { + String text2 = + javaClass.getMethods()[value].toString().replace('\n', ' ').replace('\t', ' '); + int value3 = value; + value++; + texts[value3] = text2; + } + this.pass3aJList.setListData(texts); + this.pass3aJList.setSelectionInterval(0, javaClass.getMethods().length - 1); + this.pass3bJList.setListData(texts); + this.pass3bJList.setSelectionInterval(0, javaClass.getMethods().length - 1); + verifier2 = verifier; + } + } + String[] messages = verifier2.getMessages(); + this.messagesTextPane.setBackground(messages.length == 0 ? Color.green : Color.yellow); + String text3 = ""; + int value4; + for (int value5 = value4 = 0; value5 < messages.length; value5 = value4) { + messages[value4] = messages[value4].replace('\n', ' '); + StringBuilder stringBuilder = new StringBuilder().insert(0, text3).append(messages[value4]); + value4++; + text3 = stringBuilder.append((String) "\n\n").toString(); + } + this.messagesTextPane.setText(text3); + this.setTitle(this.text + " - " + this.JUSTICE_VERSION); + } + + public void aboutMenuItem_actionPerformed(ActionEvent actionEvent) { + JOptionPane.showMessageDialog( + this, + "JustIce is a Java class file verifier.\n" + + "It was implemented by Enver Haase in 2001, 2002.\n" + + "", + this.JUSTICE_VERSION, + 1); + } + + public void newFileMenuItem_actionPerformed(ActionEvent actionEvent) { + String text; + if ((text = + JOptionPane.showInputDialog( + "Please enter the fully qualified name of a class or interface to verify:")) + != null + && !text.equals("")) { + VerifierFactory.getVerifier(text); + this.classNamesJList.setSelectedValue(text, true); + } + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/VerifierFactory.java b/src/main/java/com/allatori/lib/bcel/verifier/VerifierFactory.java new file mode 100644 index 0000000..8dc7de5 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/VerifierFactory.java @@ -0,0 +1,46 @@ +package com.allatori.lib.bcel.verifier; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Vector; + +public class VerifierFactory { + + public static Map hashMap = new HashMap(); + + public static List observers = new Vector(); + + public static void notify(String text) { + Iterator iterator2; + for (Iterator iterator3 = iterator2 = observers.iterator(); + iterator3.hasNext(); + iterator3 = iterator2) { + ((VerifierFactoryObserver) iterator2.next()).update(text); + } + } + + public static void detach(VerifierFactoryObserver verifierFactoryObserver) { + observers.remove(verifierFactoryObserver); + } + + public static Verifier getVerifier(String text) { + Verifier verifier; + if ((verifier = (Verifier) hashMap.get(text)) == null) { + verifier = new Verifier(text); + hashMap.put(text, verifier); + notify(text); + } + return verifier; + } + + public static void attach(VerifierFactoryObserver verifierFactoryObserver) { + observers.add(verifierFactoryObserver); + } + + public static Verifier[] getVerifiers() { + Verifier[] verifiers = new Verifier[hashMap.values().size()]; + return (Verifier[]) hashMap.values().toArray(verifiers); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/VerifierFactoryListModel.java b/src/main/java/com/allatori/lib/bcel/verifier/VerifierFactoryListModel.java new file mode 100644 index 0000000..86d4ae5 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/VerifierFactoryListModel.java @@ -0,0 +1,63 @@ +package com.allatori.lib.bcel.verifier; + +import java.util.ArrayList; +import java.util.TreeSet; +import javax.swing.ListModel; +import javax.swing.event.ListDataEvent; +import javax.swing.event.ListDataListener; + +public class VerifierFactoryListModel implements VerifierFactoryObserver, ListModel { + + public TreeSet cache; + + public ArrayList listeners = new ArrayList(); + + @Override + public synchronized void addListDataListener(ListDataListener listDataListener) { + this.listeners.add(listDataListener); + } + + public VerifierFactoryListModel() { + this.cache = new TreeSet(); + VerifierFactory.attach(this); + this.update(null); + } + + @Override + public synchronized Object getElementAt(int value) { + return this.cache.toArray()[value]; + } + + @Override + public synchronized void removeListDataListener(ListDataListener listDataListener) { + this.listeners.remove(listDataListener); + } + + @Override + public synchronized void update(String text) { + int size2 = this.listeners.size(); + Verifier[] verifiers; + int value = (verifiers = VerifierFactory.getVerifiers()).length; + int value2 = 0; + this.cache.clear(); + for (int index = 0; value2 < value; value2 = index) { + int value3 = index; + Verifier[] verifiers2 = verifiers; + TreeSet treeSet = this.cache; + index++; + treeSet.add(verifiers2[value3].getClassName()); + } + int value4; + for (int value5 = value4 = 0; value5 < size2; value5 = value4) { + ListDataEvent listDataEvent = new ListDataEvent(this, 0, 0, value - 1); + ListDataListener listDataListener = (ListDataListener) this.listeners.get(value4); + value4++; + listDataListener.contentsChanged(listDataEvent); + } + } + + @Override + public synchronized int getSize() { + return this.cache.size(); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/VerifierFactoryObserver.java b/src/main/java/com/allatori/lib/bcel/verifier/VerifierFactoryObserver.java new file mode 100644 index 0000000..29e9082 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/VerifierFactoryObserver.java @@ -0,0 +1,6 @@ +package com.allatori.lib.bcel.verifier; + +public interface VerifierFactoryObserver { + + void update(String text); +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/VerifyDialog$IvjEventHandler.java b/src/main/java/com/allatori/lib/bcel/verifier/VerifyDialog$IvjEventHandler.java new file mode 100644 index 0000000..8c45b2a --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/VerifyDialog$IvjEventHandler.java @@ -0,0 +1,30 @@ +package com.allatori.lib.bcel.verifier; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public class VerifyDialog$IvjEventHandler implements ActionListener { + + public final VerifyDialog this$0; + + @Override + public void actionPerformed(ActionEvent actionEvent) { + if (actionEvent.getSource() == VerifyDialog.getJButton3(this.this$0)) { + VerifyDialog.processActionEvent(this.this$0, actionEvent); + } + if (actionEvent.getSource() == VerifyDialog.getJButton2(this.this$0)) { + VerifyDialog.processActionEvent2(this.this$0, actionEvent); + } + if (actionEvent.getSource() == VerifyDialog.getJButton(this.this$0)) { + VerifyDialog.processActionEvent4(this.this$0, actionEvent); + } + if (actionEvent.getSource() == VerifyDialog.getJButton4(this.this$0)) { + VerifyDialog.processActionEvent3(this.this$0, actionEvent); + } + } + + public VerifyDialog$IvjEventHandler(VerifyDialog verifyDialog) { + super(); + this.this$0 = verifyDialog; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/VerifyDialog.java b/src/main/java/com/allatori/lib/bcel/verifier/VerifyDialog.java new file mode 100644 index 0000000..edbc68a --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/VerifyDialog.java @@ -0,0 +1,531 @@ +package com.allatori.lib.bcel.verifier; + +import com.allatori.lib.bcel.Repository; +import com.allatori.lib.bcel.verifier.ui.VerifierWindowListener; +import java.awt.Color; +import java.awt.Dialog; +import java.awt.Frame; +import java.awt.SystemColor; +import java.awt.event.ActionEvent; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JPanel; + +public class VerifyDialog extends JDialog { + + public JPanel ivjPass3Panel; + + public JButton ivjPass3Button; + + public JPanel ivjJDialogContentPane = null; + + public JButton ivjPass1Button; + + public static int classes_to_verify; + + public JPanel ivjPass1Panel = null; + + public String class_name; + + public JPanel ivjPass2Panel = null; + + public JButton ivjFlushButton; + + public JButton ivjPass2Button; + + public VerifyDialog$IvjEventHandler ivjEventHandler; + + public JButton getPass3Button() { + if (this.ivjPass3Button == null) { + try { + this.ivjPass3Button = new JButton(); + this.ivjPass3Button.setName("Pass3Button"); + this.ivjPass3Button.setText("Passes 3a+3b: Verify code arrays"); + this.ivjPass3Button.setBackground(SystemColor.controlHighlight); + this.ivjPass3Button.setBounds(100, 160, 300, 30); + this.ivjPass3Button.setActionCommand("Button2"); + } catch (Throwable throwable) { + this.handleException(throwable); + return this.ivjPass3Button; + } + return this.ivjPass3Button; + } else { + return this.ivjPass3Button; + } + } + + public void processActionEvent(ActionEvent actionEvent) { + try { + this.flushButton_ActionPerformed(actionEvent); + } catch (Throwable throwable) { + this.handleException(throwable); + } + } + + public VerifyDialog(Frame frame, String text) { + super(frame, text); + this.ivjJDialogContentPane = null; + this.ivjPass1Panel = null; + this.ivjPass2Panel = null; + this.ivjPass3Panel = null; + this.ivjPass1Button = null; + this.ivjPass2Button = null; + this.ivjPass3Button = null; + this.ivjEventHandler = new VerifyDialog$IvjEventHandler(this); + this.class_name = "java.lang.Object"; + this.ivjFlushButton = null; + } + + public VerifyDialog(Dialog dialog) { + super(dialog); + this.ivjJDialogContentPane = null; + this.ivjPass1Panel = null; + this.ivjPass2Panel = null; + this.ivjPass3Panel = null; + this.ivjPass1Button = null; + this.ivjPass2Button = null; + this.ivjPass3Button = null; + this.ivjEventHandler = new VerifyDialog$IvjEventHandler(this); + this.class_name = "java.lang.Object"; + this.ivjFlushButton = null; + } + + public VerifyDialog(String text) { + super(); + String text2 = text; + this.ivjJDialogContentPane = null; + this.ivjPass1Panel = null; + this.ivjPass2Panel = null; + this.ivjPass3Panel = null; + this.ivjPass1Button = null; + this.ivjPass2Button = null; + this.ivjPass3Button = null; + this.ivjEventHandler = new VerifyDialog$IvjEventHandler(this); + this.class_name = "java.lang.Object"; + this.ivjFlushButton = null; + int value; + if ((value = text2.lastIndexOf(".class")) != -1) { + text2 = text2.substring(0, value); + } + String text3 = text2.replace('/', '.'); + this.class_name = text3; + this.initialize(); + } + + public static void processActionEvent(VerifyDialog verifyDialog, ActionEvent actionEvent) { + verifyDialog.processActionEvent4(actionEvent); + } + + public static JButton getJButton(VerifyDialog verifyDialog) { + return verifyDialog.getPass3Button(); + } + + public void pass2Button_ActionPerformed(ActionEvent actionEvent) { + this.pass1Button_ActionPerformed(actionEvent); + VerificationResult verificationResult; + if ((verificationResult = + VerifierFactory.getVerifier(this.class_name).createVerificationResult2()) + .getStatus() + == 1) { + this.getPass2Panel().setBackground(Color.green); + this.getPass2Panel().repaint(); + } + if (verificationResult.getStatus() == 0) { + this.getPass2Panel().setBackground(Color.yellow); + this.getPass2Panel().repaint(); + } + if (verificationResult.getStatus() == 2) { + this.getPass2Panel().setBackground(Color.red); + this.getPass2Panel().repaint(); + } + } + + public void processActionEvent2(ActionEvent actionEvent) { + try { + this.pass4Button_ActionPerformed(actionEvent); + } catch (Throwable throwable) { + this.handleException(throwable); + } + } + + public void initialize() { + VerifyDialog verifyDialog; + label12: + { + try { + this.setName("VerifyDialog"); + this.setDefaultCloseOperation(2); + this.setSize(430, 280); + this.setVisible(true); + this.setModal(true); + this.setResizable(false); + this.setContentPane(this.getJDialogContentPane()); + this.initConnections(); + } catch (Throwable throwable) { + verifyDialog = this; + this.handleException(throwable); + break label12; + } + verifyDialog = this; + } + verifyDialog.setTitle("'" + this.class_name + "' verification - JustIce / BCEL"); + } + + public VerifyDialog(Dialog dialog, String text, boolean matches) { + super(dialog, text, matches); + this.ivjJDialogContentPane = null; + this.ivjPass1Panel = null; + this.ivjPass2Panel = null; + this.ivjPass3Panel = null; + this.ivjPass1Button = null; + this.ivjPass2Button = null; + this.ivjPass3Button = null; + this.ivjEventHandler = new VerifyDialog$IvjEventHandler(this); + this.class_name = "java.lang.Object"; + this.ivjFlushButton = null; + } + + public JButton getPass2Button() { + if (this.ivjPass2Button == null) { + try { + this.ivjPass2Button = new JButton(); + this.ivjPass2Button.setName("Pass2Button"); + this.ivjPass2Button.setText("Pass 2: Verify static .class file constraints"); + this.ivjPass2Button.setBackground(SystemColor.controlHighlight); + this.ivjPass2Button.setBounds(100, 100, 300, 30); + this.ivjPass2Button.setActionCommand("Button2"); + } catch (Throwable throwable) { + this.handleException(throwable); + return this.ivjPass2Button; + } + return this.ivjPass2Button; + } else { + return this.ivjPass2Button; + } + } + + public VerifyDialog(Frame frame) { + super(frame); + this.ivjJDialogContentPane = null; + this.ivjPass1Panel = null; + this.ivjPass2Panel = null; + this.ivjPass3Panel = null; + this.ivjPass1Button = null; + this.ivjPass2Button = null; + this.ivjPass3Button = null; + this.ivjEventHandler = new VerifyDialog$IvjEventHandler(this); + this.class_name = "java.lang.Object"; + this.ivjFlushButton = null; + } + + public void pass4Button_ActionPerformed(ActionEvent actionEvent) { + this.pass2Button_ActionPerformed(actionEvent); + Color color = Color.green; + Verifier verifier; + if ((verifier = VerifierFactory.getVerifier(this.class_name)) + .createVerificationResult2() + .getStatus() + == 1) { + try { + int value = Repository.lookupClass(this.class_name).getMethods().length; + for (int index = 0; index < value; index++) { + if (verifier.doPass3b(index).getStatus() != 1) { + color = Color.red; + break; + } + } + } catch (ClassNotFoundException classNotFoundException) { + classNotFoundException.printStackTrace(); + } + } else { + color = Color.yellow; + } + this.getPass3Panel().setBackground(color); + this.getPass3Panel().repaint(); + } + + public JPanel getJDialogContentPane() { + if (this.ivjJDialogContentPane == null) { + try { + this.ivjJDialogContentPane = new JPanel(); + this.ivjJDialogContentPane.setName("JDialogContentPane"); + this.ivjJDialogContentPane.setLayout(null); + this.getJDialogContentPane().add(this.getPass1Panel(), this.getPass1Panel().getName()); + this.getJDialogContentPane().add(this.getPass3Panel(), this.getPass3Panel().getName()); + this.getJDialogContentPane().add(this.getPass2Panel(), this.getPass2Panel().getName()); + this.getJDialogContentPane().add(this.getPass1Button(), this.getPass1Button().getName()); + this.getJDialogContentPane().add(this.getPass2Button(), this.getPass2Button().getName()); + this.getJDialogContentPane().add(this.getPass3Button(), this.getPass3Button().getName()); + this.getJDialogContentPane().add(this.getFlushButton(), this.getFlushButton().getName()); + } catch (Throwable throwable) { + this.handleException(throwable); + return this.ivjJDialogContentPane; + } + return this.ivjJDialogContentPane; + } else { + return this.ivjJDialogContentPane; + } + } + + public VerifyDialog(Dialog dialog, boolean matches) { + super(dialog, matches); + this.ivjJDialogContentPane = null; + this.ivjPass1Panel = null; + this.ivjPass2Panel = null; + this.ivjPass3Panel = null; + this.ivjPass1Button = null; + this.ivjPass2Button = null; + this.ivjPass3Button = null; + this.ivjEventHandler = new VerifyDialog$IvjEventHandler(this); + this.class_name = "java.lang.Object"; + this.ivjFlushButton = null; + } + + public static JButton getJButton2(VerifyDialog verifyDialog) { + return verifyDialog.getPass2Button(); + } + + public void initConnections() throws Exception { + this.getPass1Button().addActionListener(this.ivjEventHandler); + this.getPass2Button().addActionListener(this.ivjEventHandler); + this.getPass3Button().addActionListener(this.ivjEventHandler); + this.getFlushButton().addActionListener(this.ivjEventHandler); + } + + public void processActionEvent3(ActionEvent actionEvent) { + try { + this.pass2Button_ActionPerformed(actionEvent); + } catch (Throwable throwable) { + this.handleException(throwable); + } + } + + public static void processActionEvent2(VerifyDialog verifyDialog, ActionEvent actionEvent) { + verifyDialog.processActionEvent3(actionEvent); + } + + public VerifyDialog(Frame frame, String text, boolean matches) { + super(frame, text, matches); + this.ivjJDialogContentPane = null; + this.ivjPass1Panel = null; + this.ivjPass2Panel = null; + this.ivjPass3Panel = null; + this.ivjPass1Button = null; + this.ivjPass2Button = null; + this.ivjPass3Button = null; + this.ivjEventHandler = new VerifyDialog$IvjEventHandler(this); + this.class_name = "java.lang.Object"; + this.ivjFlushButton = null; + } + + public VerifyDialog(Frame frame, boolean matches) { + super(frame, matches); + this.ivjJDialogContentPane = null; + this.ivjPass1Panel = null; + this.ivjPass2Panel = null; + this.ivjPass3Panel = null; + this.ivjPass1Button = null; + this.ivjPass2Button = null; + this.ivjPass3Button = null; + this.ivjEventHandler = new VerifyDialog$IvjEventHandler(this); + this.class_name = "java.lang.Object"; + this.ivjFlushButton = null; + } + + public static void main(String[] texts) { + classes_to_verify = texts.length; + int value; + for (int value2 = value = 0; value2 < texts.length; value2 = ++value) { + try { + VerifyDialog verifyDialog = new VerifyDialog(texts[value]); + verifyDialog.setModal(true); + verifyDialog.addWindowListener(new VerifierWindowListener()); + verifyDialog.setVisible(true); + } catch (Throwable throwable) { + System.err.println("Exception occurred in main() of javax.swing.JDialog"); + throwable.printStackTrace(System.out); + } + } + } + + public void handleException(Throwable throwable) { + System.out.println("--------- UNCAUGHT EXCEPTION ---------"); + throwable.printStackTrace(System.out); + } + + public VerifyDialog() { + this.ivjPass3Panel = null; + this.ivjPass1Button = null; + this.ivjPass2Button = null; + this.ivjPass3Button = null; + this.ivjEventHandler = new VerifyDialog$IvjEventHandler(this); + this.class_name = "java.lang.Object"; + this.ivjFlushButton = null; + this.initialize(); + } + + public static JButton getJButton3(VerifyDialog verifyDialog) { + return verifyDialog.getPass1Button(); + } + + public VerifyDialog(Dialog dialog, String text) { + super(dialog, text); + this.ivjJDialogContentPane = null; + this.ivjPass1Panel = null; + this.ivjPass2Panel = null; + this.ivjPass3Panel = null; + this.ivjPass1Button = null; + this.ivjPass2Button = null; + this.ivjPass3Button = null; + this.ivjEventHandler = new VerifyDialog$IvjEventHandler(this); + this.class_name = "java.lang.Object"; + this.ivjFlushButton = null; + } + + public static void processActionEvent3(VerifyDialog verifyDialog, ActionEvent actionEvent) { + verifyDialog.processActionEvent(actionEvent); + } + + public JButton getFlushButton() { + if (this.ivjFlushButton == null) { + try { + this.ivjFlushButton = new JButton(); + this.ivjFlushButton.setName("FlushButton"); + this.ivjFlushButton.setText("Flush: Forget old verification results"); + this.ivjFlushButton.setBackground(SystemColor.controlHighlight); + this.ivjFlushButton.setBounds(60, 215, 300, 30); + this.ivjFlushButton.setForeground(Color.red); + this.ivjFlushButton.setActionCommand("FlushButton"); + } catch (Throwable throwable) { + this.handleException(throwable); + return this.ivjFlushButton; + } + return this.ivjFlushButton; + } else { + return this.ivjFlushButton; + } + } + + public JPanel getPass2Panel() { + if (this.ivjPass2Panel == null) { + try { + this.ivjPass2Panel = new JPanel(); + this.ivjPass2Panel.setName("Pass2Panel"); + this.ivjPass2Panel.setLayout(null); + this.ivjPass2Panel.setBackground(SystemColor.controlShadow); + this.ivjPass2Panel.setBounds(30, 90, 50, 50); + } catch (Throwable throwable) { + this.handleException(throwable); + return this.ivjPass2Panel; + } + return this.ivjPass2Panel; + } else { + return this.ivjPass2Panel; + } + } + + public static void processActionEvent4(VerifyDialog verifyDialog, ActionEvent actionEvent) { + verifyDialog.processActionEvent2(actionEvent); + } + + public void flushButton_ActionPerformed(ActionEvent actionEvent) { + VerifierFactory.getVerifier(this.class_name).flush(); + Repository.removeClass(this.class_name); + this.getPass1Panel().setBackground(Color.gray); + this.getPass1Panel().repaint(); + this.getPass2Panel().setBackground(Color.gray); + this.getPass2Panel().repaint(); + this.getPass3Panel().setBackground(Color.gray); + this.getPass3Panel().repaint(); + } + + public JButton getPass1Button() { + if (this.ivjPass1Button == null) { + try { + this.ivjPass1Button = new JButton(); + this.ivjPass1Button.setName("Pass1Button"); + this.ivjPass1Button.setText("Pass1: Verify binary layout of .class file"); + this.ivjPass1Button.setBackground(SystemColor.controlHighlight); + this.ivjPass1Button.setBounds(100, 40, 300, 30); + this.ivjPass1Button.setActionCommand("Button1"); + } catch (Throwable throwable) { + this.handleException(throwable); + return this.ivjPass1Button; + } + return this.ivjPass1Button; + } else { + return this.ivjPass1Button; + } + } + + public static int getClasses_to_verify() { + return classes_to_verify; + } + + public JPanel getPass3Panel() { + if (this.ivjPass3Panel == null) { + try { + this.ivjPass3Panel = new JPanel(); + this.ivjPass3Panel.setName("Pass3Panel"); + this.ivjPass3Panel.setLayout(null); + this.ivjPass3Panel.setBackground(SystemColor.controlShadow); + this.ivjPass3Panel.setBounds(30, 150, 50, 50); + } catch (Throwable throwable) { + this.handleException(throwable); + return this.ivjPass3Panel; + } + return this.ivjPass3Panel; + } else { + return this.ivjPass3Panel; + } + } + + public void pass1Button_ActionPerformed(ActionEvent actionEvent) { + VerificationResult verificationResult; + if ((verificationResult = + VerifierFactory.getVerifier(this.class_name).createVerificationResult()) + .getStatus() + == 1) { + this.getPass1Panel().setBackground(Color.green); + this.getPass1Panel().repaint(); + } + if (verificationResult.getStatus() == 2) { + this.getPass1Panel().setBackground(Color.red); + this.getPass1Panel().repaint(); + } + } + + public static JButton getJButton4(VerifyDialog verifyDialog) { + return verifyDialog.getFlushButton(); + } + + public JPanel getPass1Panel() { + if (this.ivjPass1Panel == null) { + try { + this.ivjPass1Panel = new JPanel(); + this.ivjPass1Panel.setName("Pass1Panel"); + this.ivjPass1Panel.setLayout(null); + this.ivjPass1Panel.setBackground(SystemColor.controlShadow); + this.ivjPass1Panel.setBounds(30, 30, 50, 50); + } catch (Throwable throwable) { + this.handleException(throwable); + return this.ivjPass1Panel; + } + return this.ivjPass1Panel; + } else { + return this.ivjPass1Panel; + } + } + + public static int calculateCount() { + return classes_to_verify--; + } + + public void processActionEvent4(ActionEvent actionEvent) { + try { + this.pass1Button_ActionPerformed(actionEvent); + } catch (Throwable throwable) { + this.handleException(throwable); + } + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/exc/AssertionViolatedException.java b/src/main/java/com/allatori/lib/bcel/verifier/exc/AssertionViolatedException.java new file mode 100644 index 0000000..145a2ea --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/exc/AssertionViolatedException.java @@ -0,0 +1,38 @@ +package com.allatori.lib.bcel.verifier.exc; + +public final class AssertionViolatedException extends RuntimeException { + + public String detailMessage; + + public AssertionViolatedException(String text) { + super("INTERNAL ERROR: " + text); + this.detailMessage = super.getMessage(); + } + + public static void main(String[] texts) { + AssertionViolatedException assertionViolatedException = new AssertionViolatedException("Oops!"); + assertionViolatedException.extendMessage("\nFOUND:\n\t", "\nExiting!!\n"); + throw assertionViolatedException; + } + + @Override + public String getMessage() { + return this.detailMessage; + } + + public void extendMessage(String text, String text2) { + String text3 = text2; + if (text == null) { + text = ""; + } + if (this.detailMessage == null) { + this.detailMessage = ""; + } + if (text3 == null) { + text3 = ""; + } + this.detailMessage = "" + text + this.detailMessage + text3; + } + + public AssertionViolatedException() {} +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/exc/ClassConstraintException.java b/src/main/java/com/allatori/lib/bcel/verifier/exc/ClassConstraintException.java new file mode 100644 index 0000000..3363c3e --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/exc/ClassConstraintException.java @@ -0,0 +1,10 @@ +package com.allatori.lib.bcel.verifier.exc; + +public class ClassConstraintException extends LoadingException { + + public ClassConstraintException(String text) { + super(text); + } + + public ClassConstraintException() {} +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/exc/CodeConstraintException.java b/src/main/java/com/allatori/lib/bcel/verifier/exc/CodeConstraintException.java new file mode 100644 index 0000000..4943a9b --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/exc/CodeConstraintException.java @@ -0,0 +1,10 @@ +package com.allatori.lib.bcel.verifier.exc; + +public abstract class CodeConstraintException extends VerificationException { + + public CodeConstraintException(String text) { + super(text); + } + + public CodeConstraintException() {} +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/exc/InvalidMethodException.java b/src/main/java/com/allatori/lib/bcel/verifier/exc/InvalidMethodException.java new file mode 100644 index 0000000..840609f --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/exc/InvalidMethodException.java @@ -0,0 +1,8 @@ +package com.allatori.lib.bcel.verifier.exc; + +public class InvalidMethodException extends RuntimeException { + + public InvalidMethodException(String text) { + super(text); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/exc/LinkingConstraintException.java b/src/main/java/com/allatori/lib/bcel/verifier/exc/LinkingConstraintException.java new file mode 100644 index 0000000..15c0440 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/exc/LinkingConstraintException.java @@ -0,0 +1,3 @@ +package com.allatori.lib.bcel.verifier.exc; + +public class LinkingConstraintException extends StructuralCodeConstraintException {} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/exc/LoadingException.java b/src/main/java/com/allatori/lib/bcel/verifier/exc/LoadingException.java new file mode 100644 index 0000000..eb1ff47 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/exc/LoadingException.java @@ -0,0 +1,10 @@ +package com.allatori.lib.bcel.verifier.exc; + +public class LoadingException extends VerificationException { + + public LoadingException() {} + + public LoadingException(String text) { + super(text); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/exc/StaticCodeConstraintException.java b/src/main/java/com/allatori/lib/bcel/verifier/exc/StaticCodeConstraintException.java new file mode 100644 index 0000000..0cf7191 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/exc/StaticCodeConstraintException.java @@ -0,0 +1,8 @@ +package com.allatori.lib.bcel.verifier.exc; + +public abstract class StaticCodeConstraintException extends CodeConstraintException { + + public StaticCodeConstraintException(String text) { + super(text); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/exc/StaticCodeInstructionConstraintException.java b/src/main/java/com/allatori/lib/bcel/verifier/exc/StaticCodeInstructionConstraintException.java new file mode 100644 index 0000000..4b9cf8d --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/exc/StaticCodeInstructionConstraintException.java @@ -0,0 +1,8 @@ +package com.allatori.lib.bcel.verifier.exc; + +public class StaticCodeInstructionConstraintException extends StaticCodeConstraintException { + + public StaticCodeInstructionConstraintException(String text) { + super(text); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/exc/StaticCodeInstructionOperandConstraintException.java b/src/main/java/com/allatori/lib/bcel/verifier/exc/StaticCodeInstructionOperandConstraintException.java new file mode 100644 index 0000000..7687f0b --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/exc/StaticCodeInstructionOperandConstraintException.java @@ -0,0 +1,8 @@ +package com.allatori.lib.bcel.verifier.exc; + +public class StaticCodeInstructionOperandConstraintException extends StaticCodeConstraintException { + + public StaticCodeInstructionOperandConstraintException(String text) { + super(text); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/exc/StructuralCodeConstraintException.java b/src/main/java/com/allatori/lib/bcel/verifier/exc/StructuralCodeConstraintException.java new file mode 100644 index 0000000..d8c9f4f --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/exc/StructuralCodeConstraintException.java @@ -0,0 +1,10 @@ +package com.allatori.lib.bcel.verifier.exc; + +public class StructuralCodeConstraintException extends CodeConstraintException { + + public StructuralCodeConstraintException(String text) { + super(text); + } + + public StructuralCodeConstraintException() {} +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/exc/Utility.java b/src/main/java/com/allatori/lib/bcel/verifier/exc/Utility.java new file mode 100644 index 0000000..0f80542 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/exc/Utility.java @@ -0,0 +1,14 @@ +package com.allatori.lib.bcel.verifier.exc; + +import java.io.PrintWriter; +import java.io.StringWriter; + +public final class Utility { + + public static String getStackTrace(Throwable throwable) { + StringWriter stringWriter = new StringWriter(); + PrintWriter printWriter = new PrintWriter(stringWriter); + throwable.printStackTrace(printWriter); + return stringWriter.toString(); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/exc/VerificationException.java b/src/main/java/com/allatori/lib/bcel/verifier/exc/VerificationException.java new file mode 100644 index 0000000..3b29112 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/exc/VerificationException.java @@ -0,0 +1,10 @@ +package com.allatori.lib.bcel.verifier.exc; + +public abstract class VerificationException extends VerifierConstraintViolatedException { + + public VerificationException(String text) { + super(text); + } + + public VerificationException() {} +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/exc/VerifierConstraintViolatedException.java b/src/main/java/com/allatori/lib/bcel/verifier/exc/VerifierConstraintViolatedException.java new file mode 100644 index 0000000..fd19e14 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/exc/VerifierConstraintViolatedException.java @@ -0,0 +1,32 @@ +package com.allatori.lib.bcel.verifier.exc; + +public abstract class VerifierConstraintViolatedException extends RuntimeException { + + public String detailMessage; + + public VerifierConstraintViolatedException(String detailMessage) { + super(detailMessage); + this.detailMessage = detailMessage; + } + + @Override + public String getMessage() { + return this.detailMessage; + } + + public VerifierConstraintViolatedException() {} + + public void extendMessage(String text, String text2) { + String text3 = text2; + if (text == null) { + text = ""; + } + if (this.detailMessage == null) { + this.detailMessage = ""; + } + if (text3 == null) { + text3 = ""; + } + this.detailMessage = "" + text + this.detailMessage + text3; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/statics/IntList.java b/src/main/java/com/allatori/lib/bcel/verifier/statics/IntList.java new file mode 100644 index 0000000..049cc40 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/statics/IntList.java @@ -0,0 +1,25 @@ +package com.allatori.lib.bcel.verifier.statics; + +import java.util.ArrayList; +import java.util.List; + +public class IntList { + + public List theList = new ArrayList(); + + public void add(int value) { + this.theList.add(new Integer(value)); + } + + public boolean contains(int value) { + Integer[] values = new Integer[this.theList.size()]; + this.theList.toArray(values); + int value2 = 0; + for (int value3 = value2; value3 < values.length; value3 = ++value2) { + if (value == values[value2]) { + return true; + } + } + return false; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/statics/LocalVariableInfo.java b/src/main/java/com/allatori/lib/bcel/verifier/statics/LocalVariableInfo.java new file mode 100644 index 0000000..270a7ef --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/statics/LocalVariableInfo.java @@ -0,0 +1,62 @@ +package com.allatori.lib.bcel.verifier.statics; + +import com.allatori.lib.bcel.generic.Type; +import com.allatori.lib.bcel.verifier.exc.ClassConstraintException; +import java.util.Hashtable; + +public class LocalVariableInfo { + + public Hashtable types = new Hashtable(); + + public Hashtable names = new Hashtable(); + + public Type getType(int value) { + return (Type) this.types.get(Integer.toString(value)); + } + + public void add(int value, String text, Type type) { + if (this.getName(value) != null && !this.getName(value).equals(text)) { + throw new ClassConstraintException( + ("At bytecode offset '" + + value + + "' a local variable has two different names: '" + + this.getName(value) + + "' and '" + + text + + "'.")); + } + if (this.getType(value) != null && !this.getType(value).equals(type)) { + throw new ClassConstraintException( + ("At bytecode offset '" + + value + + "' a local variable has two different types: '" + + this.getType(value) + + "' and '" + + type + + "'.")); + } + this.setName(value, text); + this.setType(value, type); + } + + public void setName(int value, String text) { + this.names.put(Integer.toString(value), text); + } + + public void setType(int value, Type type) { + this.types.put(Integer.toString(value), type); + } + + public void add(String text, int value, int value2, Type type) { + int value3; + for (int value4 = value3 = value; value4 <= value + value2; value4 = value3) { + int value5 = value3; + value3++; + this.add(value5, text, type); + } + } + + public String getName(int value) { + return (String) this.names.get(Integer.toString(value)); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/statics/LocalVariablesInfo.java b/src/main/java/com/allatori/lib/bcel/verifier/statics/LocalVariablesInfo.java new file mode 100644 index 0000000..08763ff --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/statics/LocalVariablesInfo.java @@ -0,0 +1,47 @@ +package com.allatori.lib.bcel.verifier.statics; + +import com.allatori.lib.bcel.generic.Type; +import com.allatori.lib.bcel.verifier.exc.AssertionViolatedException; + +public class LocalVariablesInfo { + + public LocalVariableInfo[] localVariableInfos; + + public void add(int value, String text, int value2, int value3, Type type) { + if (value >= 0 && value < this.localVariableInfos.length) { + this.localVariableInfos[value].add(text, value2, value3, type); + if (type == Type.LONG) { + this.localVariableInfos[value + 1].add( + text, value2, value3, UpperWordType.getUpperWordType()); + } + if (type == Type.DOUBLE) { + this.localVariableInfos[value + 1].add( + text, value2, value3, UpperWordType2.getUpperWordType2()); + } + } else { + throw new AssertionViolatedException( + "Slot number for local variable information out of range."); + } + } + + public LocalVariablesInfo(int value) { + this.localVariableInfos = new LocalVariableInfo[value]; + int value2; + for (int value3 = value2 = 0; value3 < value; value3 = value2) { + LocalVariableInfo[] localVariableInfos2 = this.localVariableInfos; + LocalVariableInfo localVariableInfo = new LocalVariableInfo(); + int value4 = value2; + value2++; + localVariableInfos2[value4] = localVariableInfo; + } + } + + public LocalVariableInfo getLocalVariableInfo(int value) { + if (value >= 0 && value < this.localVariableInfos.length) { + return this.localVariableInfos[value]; + } else { + throw new AssertionViolatedException( + "Slot number for local variable information out of range."); + } + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/statics/Pass1Verifier.java b/src/main/java/com/allatori/lib/bcel/verifier/statics/Pass1Verifier.java new file mode 100644 index 0000000..84efc0d --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/statics/Pass1Verifier.java @@ -0,0 +1,71 @@ +package com.allatori.lib.bcel.verifier.statics; + +import com.allatori.internal.VerifierConstraintViolatedExceptionSupport; +import com.allatori.lib.bcel.Repository; +import com.allatori.lib.bcel.classfile.ClassFormatException; +import com.allatori.lib.bcel.classfile.JavaClass; +import com.allatori.lib.bcel.verifier.PassVerifier; +import com.allatori.lib.bcel.verifier.VerificationResult; +import com.allatori.lib.bcel.verifier.Verifier; +import com.allatori.lib.bcel.verifier.exc.Utility; + +public final class Pass1Verifier extends PassVerifier { + + public JavaClass jc; + + public Verifier myOwner; + + public JavaClass getJavaClass() { + if (this.jc == null) { + try { + this.jc = Repository.lookupClass(this.myOwner.getClassName()); + } catch (ClassNotFoundException classNotFoundException) { + return this.jc; + } + return this.jc; + } else { + return this.jc; + } + } + + @Override + public VerificationResult getVerificationResult() { + JavaClass javaClass; + try { + if ((javaClass = this.getJavaClass()) != null + && !this.myOwner.getClassName().equals(javaClass.getText2())) { + throw new VerifierConstraintViolatedExceptionSupport( + ("Wrong name: the internal name of the .class file '" + + javaClass.getText2() + + "' does not match the file's name '" + + this.myOwner.getClassName() + + "'.")); + } + } catch ( + VerifierConstraintViolatedExceptionSupport verifierConstraintViolatedExceptionSupport) { + return new VerificationResult(2, verifierConstraintViolatedExceptionSupport.getMessage()); + } catch (ClassFormatException classFormatException) { + return new VerificationResult(2, classFormatException.getMessage()); + } catch (RuntimeException runtimeException) { + return new VerificationResult( + 2, + "Parsing via BCEL did not succeed. " + + runtimeException.getClass().getName() + + " occured:\n" + + Utility.getStackTrace(runtimeException)); + } + return javaClass != null + ? VerificationResult.VERIFICATION_RESULT2 + : new VerificationResult(2, "Repository.lookup() failed. FILE NOT FOUND?"); + } + + public Pass1Verifier(Verifier verifier) { + super(); + this.myOwner = verifier; + } + + @Override + public String[] getMessages() { + return super.getMessages(); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/statics/Pass2Verifier$1.java b/src/main/java/com/allatori/lib/bcel/verifier/statics/Pass2Verifier$1.java new file mode 100644 index 0000000..aa727da --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/statics/Pass2Verifier$1.java @@ -0,0 +1,3 @@ +package com.allatori.lib.bcel.verifier.statics; + +public class Pass2Verifier$1 {} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/statics/Pass2Verifier$CPESSC_Visitor.java b/src/main/java/com/allatori/lib/bcel/verifier/statics/Pass2Verifier$CPESSC_Visitor.java new file mode 100644 index 0000000..521b666 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/statics/Pass2Verifier$CPESSC_Visitor.java @@ -0,0 +1,1223 @@ +package com.allatori.lib.bcel.verifier.statics; + +import com.allatori.lib.bcel.Repository; +import com.allatori.lib.bcel.classfile.Attribute; +import com.allatori.lib.bcel.classfile.ClassFormatException; +import com.allatori.lib.bcel.classfile.Code; +import com.allatori.lib.bcel.classfile.CodeException; +import com.allatori.lib.bcel.classfile.Constant; +import com.allatori.lib.bcel.classfile.ConstantClass; +import com.allatori.lib.bcel.classfile.ConstantDouble; +import com.allatori.lib.bcel.classfile.ConstantFieldref; +import com.allatori.lib.bcel.classfile.ConstantFloat; +import com.allatori.lib.bcel.classfile.ConstantInteger; +import com.allatori.lib.bcel.classfile.ConstantInterfaceMethodref; +import com.allatori.lib.bcel.classfile.ConstantLong; +import com.allatori.lib.bcel.classfile.ConstantMethodref; +import com.allatori.lib.bcel.classfile.ConstantNameAndType; +import com.allatori.lib.bcel.classfile.ConstantPool; +import com.allatori.lib.bcel.classfile.ConstantString; +import com.allatori.lib.bcel.classfile.ConstantUtf8; +import com.allatori.lib.bcel.classfile.ConstantValue; +import com.allatori.lib.bcel.classfile.Deprecated; +import com.allatori.lib.bcel.classfile.DescendingVisitor; +import com.allatori.lib.bcel.classfile.EmptyVisitor; +import com.allatori.lib.bcel.classfile.ExceptionTable; +import com.allatori.lib.bcel.classfile.Field; +import com.allatori.lib.bcel.classfile.InnerClass; +import com.allatori.lib.bcel.classfile.InnerClasses; +import com.allatori.lib.bcel.classfile.JavaClass; +import com.allatori.lib.bcel.classfile.LineNumber; +import com.allatori.lib.bcel.classfile.LineNumberTable; +import com.allatori.lib.bcel.classfile.LocalVariable; +import com.allatori.lib.bcel.classfile.LocalVariableTable; +import com.allatori.lib.bcel.classfile.Method; +import com.allatori.lib.bcel.classfile.Node; +import com.allatori.lib.bcel.classfile.SourceFile; +import com.allatori.lib.bcel.classfile.Synthetic; +import com.allatori.lib.bcel.classfile.Unknown; +import com.allatori.lib.bcel.classfile.Visitor; +import com.allatori.lib.bcel.generic.ArrayType; +import com.allatori.lib.bcel.generic.ObjectType; +import com.allatori.lib.bcel.generic.Type; +import com.allatori.lib.bcel.verifier.VerificationResult; +import com.allatori.lib.bcel.verifier.VerifierFactory; +import com.allatori.lib.bcel.verifier.exc.AssertionViolatedException; +import com.allatori.lib.bcel.verifier.exc.ClassConstraintException; +import com.allatori.lib.bcel.verifier.exc.LoadingException; +import java.util.HashSet; +import java.util.Locale; +import java.util.Set; + +public class Pass2Verifier$CPESSC_Visitor extends EmptyVisitor implements Visitor { + + public Class CONST_Float; + + public Set field_names; + + public Set method_names_and_desc; + + public Set field_names_and_desc; + + public DescendingVisitor carrier; + + public Class CONST_NameAndType; + + public Class CONST_Long; + + public Class CONST_Double; + + public final JavaClass jc; + + public final int cplen; + + public Class CONST_Integer; + + public Class CONST_Class; + + public Class CONST_String; + + public final ConstantPool cp; + + public final Pass2Verifier this$0; + + public Class CONST_Utf8; + + @Override + public void visitField(Field field) { + if (this.jc.isEnabled17()) { + int value = 0; + if (field.isEnabled9()) { + value++; + } + if (field.isEnabled13()) { + value++; + } + if (field.isEnabled6()) { + value++; + } + if (value > 1) { + throw new LoadingException( + ("Field '" + + Pass2Verifier.getText(field) + + "' must only have at most one of its ACC_PRIVATE, ACC_PROTECTED, ACC_PUBLIC" + + " modifiers set.")); + } + if (field.isEnabled3() && field.isEnabled()) { + throw new LoadingException( + ("Field '" + + Pass2Verifier.getText(field) + + "' must only have at most one of its ACC_FINAL, ACC_VOLATILE modifiers set.")); + } + } else { + if (!field.isEnabled6()) { + throw new LoadingException( + ("Interface field '" + + Pass2Verifier.getText(field) + + "' must have the ACC_PUBLIC modifier set but hasn't!")); + } + if (!field.isEnabled11()) { + throw new LoadingException( + ("Interface field '" + + Pass2Verifier.getText(field) + + "' must have the ACC_STATIC modifier set but hasn't!")); + } + if (!field.isEnabled3()) { + throw new LoadingException( + ("Interface field '" + + Pass2Verifier.getText(field) + + "' must have the ACC_FINAL modifier set but hasn't!")); + } + } + if ((field.getAccess_flags2() & -224) > 0) { + this.this$0.addMessage( + "Field '" + + Pass2Verifier.getText(field) + + "' has access flag(s) other than ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED," + + " ACC_STATIC, ACC_FINAL, ACC_VOLATILE, ACC_TRANSIENT set (ignored)."); + } + this.checkIndex(field, field.getCount3(), this.CONST_Utf8); + String text; + if (!Pass2Verifier.matchesText(text = field.getText())) { + throw new LoadingException( + ("Field '" + + Pass2Verifier.getText(field) + + "' has illegal name '" + + field.getText() + + "'.")); + } + this.checkIndex(field, field.getCount(), this.CONST_Utf8); + String bytes = ((ConstantUtf8) this.cp.getConstant(field.getCount())).getBytes(); + try { + Type.getType(bytes); + } catch (ClassFormatException classFormatException) { + throw new LoadingException( + ("Illegal descriptor (==signature) '" + + bytes + + "' used by '" + + Pass2Verifier.getText(field) + + "'.")); + } + String text2 = "" + text + bytes; + if (this.field_names_and_desc.contains(text2)) { + throw new LoadingException( + ("No two fields (like '" + + Pass2Verifier.getText(field) + + "') are allowed have same names and descriptors!")); + } + if (this.field_names.contains(text)) { + this.this$0.addMessage( + "More than one field of name '" + + text + + "' detected (but with different type descriptors). This is very unusual."); + } + this.field_names_and_desc.add(text2); + this.field_names.add(text); + Attribute[] attributes = field.getAttributes(); + int value2 = 0; + for (int value3 = value2; value3 < attributes.length; value3 = ++value2) { + if (!(attributes[value2] instanceof ConstantValue) + && !(attributes[value2] instanceof Synthetic) + && !(attributes[value2] instanceof Deprecated)) { + this.this$0.addMessage( + "Attribute '" + + Pass2Verifier.getText(attributes[value2]) + + "' as an attribute of Field '" + + Pass2Verifier.getText(field) + + "' is unknown and will therefore be ignored."); + } + if (!(attributes[value2] instanceof ConstantValue)) { + this.this$0.addMessage( + "Attribute '" + + Pass2Verifier.getText(attributes[value2]) + + "' as an attribute of Field '" + + Pass2Verifier.getText(field) + + "' is not a ConstantValue and is therefore only of use for debuggers and such."); + } + } + } + + @Override + public void visitLocalVariable(LocalVariable localVariable) {} + + @Override + public void visitUnknown(Unknown unknown) { + this.checkIndex(unknown, unknown.getName_index(), this.CONST_Utf8); + this.this$0.addMessage( + "Unknown attribute '" + + Pass2Verifier.getText(unknown) + + "'. This attribute is not known in any context!"); + } + + @Override + public void visitLineNumberTable(LineNumberTable lineNumberTable) { + this.checkIndex(lineNumberTable, lineNumberTable.getName_index(), this.CONST_Utf8); + String text; + if (!(text = ((ConstantUtf8) this.cp.getConstant(lineNumberTable.getName_index())).getBytes()) + .equals("LineNumberTable")) { + throw new LoadingException( + ("The LineNumberTable attribute '" + + Pass2Verifier.getText(lineNumberTable) + + "' is not correctly named 'LineNumberTable' but '" + + text + + "'.")); + } + } + + @Override + public void visitCodeException(CodeException codeException) {} + + @Override + public void visitConstantFloat(ConstantFloat constantFloat) { + if (constantFloat.getTag() != 4) { + throw new LoadingException( + ("Wrong constant tag in '" + Pass2Verifier.getText(constantFloat) + "'.")); + } + } + + @Override + public void visitConstantFieldref(ConstantFieldref constantFieldref) { + if (constantFieldref.getTag() != 9) { + throw new LoadingException( + ("Wrong constant tag in '" + Pass2Verifier.getText(constantFieldref) + "'.")); + } + this.checkIndex(constantFieldref, constantFieldref.getClass_index(), this.CONST_Class); + this.checkIndex( + constantFieldref, constantFieldref.getName_and_type_index(), this.CONST_NameAndType); + } + + @Override + public void visitConstantString(ConstantString constantString) { + if (constantString.getTag() != 8) { + throw new LoadingException( + ("Wrong constant tag in '" + Pass2Verifier.getText(constantString) + "'.")); + } + this.checkIndex(constantString, constantString.getStringIndex(), this.CONST_Utf8); + } + + @Override + public void visitExceptionTable(ExceptionTable exceptionTable) { + JavaClass javaClass; + try { + this.checkIndex(exceptionTable, exceptionTable.getName_index(), this.CONST_Utf8); + String text; + if (!(text = ((ConstantUtf8) this.cp.getConstant(exceptionTable.getName_index())).getBytes()) + .equals("Exceptions")) { + throw new LoadingException( + ("The Exceptions attribute '" + + Pass2Verifier.getText(exceptionTable) + + "' is not correctly named 'Exceptions' but '" + + text + + "'.")); + } + int[] exceptionIndexTable = exceptionTable.getExceptionIndexTable(); + for (int index = 0; index < exceptionIndexTable.length; index++) { + this.checkIndex(exceptionTable, exceptionIndexTable[index], this.CONST_Class); + ConstantClass constantClass; + ConstantClass constantClass2 = + constantClass = (ConstantClass) this.cp.getConstant(exceptionIndexTable[index]); + this.checkIndex(constantClass2, constantClass2.getNameIndex(), this.CONST_Utf8); + String text2; + VerificationResult verificationResult; + if ((verificationResult = + VerifierFactory.getVerifier( + text2 = + ((ConstantUtf8) this.cp.getConstant(constantClass.getNameIndex())) + .getBytes() + .replace('/', '.')) + .createVerificationResult()) + != VerificationResult.VERIFICATION_RESULT2) { + throw new LoadingException( + ("Exceptions attribute '" + + Pass2Verifier.getText(exceptionTable) + + "' references '" + + text2 + + "' as an Exception but it does not pass verification pass 1: " + + verificationResult)); + } + JavaClass javaClass2 = Repository.lookupClass(text2); + JavaClass javaClass3 = Repository.lookupClass(Type.THROWABLE.getClassName()); + JavaClass javaClass4 = Repository.lookupClass(Type.OBJECT.getClassName()); + JavaClass javaClass5 = javaClass2; + while (true) { + if (javaClass5 == javaClass4) { + javaClass = javaClass2; + break; + } + if (javaClass2 == javaClass3) { + javaClass = javaClass2; + break; + } + VerificationResult verificationResult2; + if ((verificationResult2 = + VerifierFactory.getVerifier(javaClass2.getText5()).createVerificationResult()) + != VerificationResult.VERIFICATION_RESULT2) { + throw new LoadingException( + ("Exceptions attribute '" + + Pass2Verifier.getText(exceptionTable) + + "' references '" + + text2 + + "' as an Exception but '" + + javaClass2.getText5() + + "' in the ancestor hierachy does not pass verification pass 1: " + + verificationResult2)); + } + javaClass5 = javaClass2 = Repository.lookupClass(javaClass2.getText5()); + } + if (javaClass != javaClass3) { + throw new LoadingException( + ("Exceptions attribute '" + + Pass2Verifier.getText(exceptionTable) + + "' references '" + + text2 + + "' as an Exception but it is not a subclass of '" + + javaClass3.getText2() + + "'.")); + } + } + } catch (ClassNotFoundException classNotFoundException) { + throw new AssertionViolatedException(("Missing class: " + classNotFoundException.toString())); + } + } + + @Override + public void visitConstantValue(ConstantValue constantValue) { + this.checkIndex(constantValue, constantValue.getName_index(), this.CONST_Utf8); + String text; + if (!(text = ((ConstantUtf8) this.cp.getConstant(constantValue.getName_index())).getBytes()) + .equals("ConstantValue")) { + throw new LoadingException( + ("The ConstantValue attribute '" + + Pass2Verifier.getText(constantValue) + + "' is not correctly named 'ConstantValue' but '" + + text + + "'.")); + } + Object result; + if ((result = this.carrier.predecessor()) instanceof Field) { + Field field = (Field) result; + Type type = Type.getType(((ConstantUtf8) this.cp.getConstant(field.getCount())).getBytes()); + int value; + if ((value = constantValue.getConstantValueIndex()) >= 0 && value < this.cplen) { + Constant constant = this.cp.getConstant(value); + if (!this.CONST_Long.isInstance(constant) || !type.equals(Type.LONG)) { + if (!this.CONST_Float.isInstance(constant) || !type.equals(Type.FLOAT)) { + if (!this.CONST_Double.isInstance(constant) || !type.equals(Type.DOUBLE)) { + if (!this.CONST_Integer.isInstance(constant) + || !type.equals(Type.INT) + && !type.equals(Type.SHORT) + && !type.equals(Type.CHAR) + && !type.equals(Type.BYTE) + && !type.equals(Type.BOOLEAN)) { + if (!this.CONST_String.isInstance(constant) || !type.equals(Type.STRING)) { + throw new LoadingException( + ("Illegal type of ConstantValue '" + + constantValue + + "' embedding Constant '" + + constant + + "'. It is referenced by field '" + + Pass2Verifier.getText(field) + + "' expecting a different type: '" + + type + + "'.")); + } + } + } + } + } + } else { + throw new LoadingException( + ("Invalid index '" + + value + + "' used by '" + + Pass2Verifier.getText(constantValue) + + "'.")); + } + } + } + + @Override + public void visitInnerClass(InnerClass innerClass) {} + + public Pass2Verifier$CPESSC_Visitor(Pass2Verifier pass2Verifier, JavaClass javaClass) { + super(); + this.this$0 = pass2Verifier; + this.field_names = new HashSet(); + this.field_names_and_desc = new HashSet(); + this.method_names_and_desc = new HashSet(); + this.jc = javaClass; + this.cp = javaClass.getConstantPool(); + this.cplen = this.cp.getLength(); + this.CONST_Class = ConstantClass.class; + this.CONST_String = ConstantString.class; + this.CONST_Integer = ConstantInteger.class; + this.CONST_Float = ConstantFloat.class; + this.CONST_Long = ConstantLong.class; + this.CONST_Double = ConstantDouble.class; + this.CONST_NameAndType = ConstantNameAndType.class; + this.CONST_Utf8 = ConstantUtf8.class; + this.carrier = new DescendingVisitor(javaClass, this); + this.carrier.visit(); + } + + public Pass2Verifier$CPESSC_Visitor( + Pass2Verifier pass2Verifier, JavaClass javaClass, Pass2Verifier$1 pass2Verifier$1) { + this(pass2Verifier, javaClass); + } + + @Override + public void visitLineNumber(LineNumber lineNumber) {} + + @Override + public void visitJavaClass(JavaClass javaClass) { + Attribute[] attributes = javaClass.getAttributes(); + byte value = 0; + byte value2 = 0; + boolean matches = new Pass2Verifier$InnerClassDetector(this.jc).innerClassReferenced(); + int value3; + for (int value4 = value3 = 0; value4 < attributes.length; value4 = ++value3) { + if (!(attributes[value3] instanceof SourceFile) + && !(attributes[value3] instanceof Deprecated) + && !(attributes[value3] instanceof InnerClasses) + && !(attributes[value3] instanceof Synthetic)) { + this.this$0.addMessage( + "Attribute '" + + Pass2Verifier.getText(attributes[value3]) + + "' as an attribute of the ClassFile structure '" + + Pass2Verifier.getText(javaClass) + + "' is unknown and will therefore be ignored."); + } + Attribute[] attributes2; + if (attributes[value3] instanceof SourceFile) { + if (value != 0) { + throw new LoadingException( + ("A ClassFile structure (like '" + + Pass2Verifier.getText(javaClass) + + "') may have no more than one SourceFile attribute.")); + } + value = 1; + attributes2 = attributes; + } else { + attributes2 = attributes; + } + if (attributes2[value3] instanceof InnerClasses) { + boolean matches2; + if (value2 == 0) { + value2 = 1; + matches2 = matches; + } else { + if (matches) { + throw new LoadingException( + ("A Classfile structure (like '" + + Pass2Verifier.getText(javaClass) + + "') must have exactly one InnerClasses attribute if at least one Inner Class" + + " is referenced (which is the case). More than one InnerClasses attribute was" + + " found.")); + } + matches2 = matches; + } + if (!matches2) { + this.this$0.addMessage( + "No referenced Inner Class found, but InnerClasses attribute '" + + Pass2Verifier.getText(attributes[value3]) + + "' found. Strongly suggest removal of that attribute."); + } + } + } + if (matches && value2 == 0) { + this.this$0.addMessage( + "A Classfile structure (like '" + + Pass2Verifier.getText(javaClass) + + "') must have exactly one InnerClasses attribute if at least one Inner Class is" + + " referenced (which is the case). No InnerClasses attribute was found."); + } + } + + @Override + public void visitConstantDouble(ConstantDouble constantDouble) { + if (constantDouble.getTag() != 6) { + throw new LoadingException( + ("Wrong constant tag in '" + Pass2Verifier.getText(constantDouble) + "'.")); + } + } + + @Override + public void visitSynthetic(Synthetic synthetic) { + this.checkIndex(synthetic, synthetic.getName_index(), this.CONST_Utf8); + String text; + if (!(text = ((ConstantUtf8) this.cp.getConstant(synthetic.getName_index())).getBytes()) + .equals("Synthetic")) { + throw new LoadingException( + ("The Synthetic attribute '" + + Pass2Verifier.getText(synthetic) + + "' is not correctly named 'Synthetic' but '" + + text + + "'.")); + } + } + + @Override + public void visitConstantUtf8(ConstantUtf8 constantUtf8) { + if (constantUtf8.getTag() != 1) { + throw new LoadingException( + ("Wrong constant tag in '" + Pass2Verifier.getText(constantUtf8) + "'.")); + } + } + + @Override + public void visitLocalVariableTable(LocalVariableTable localVariableTable) {} + + public void checkIndex(Node node, int value, Class classValue) { + if (value >= 0 && value < this.cplen) { + Constant constant = this.cp.getConstant(value); + if (!classValue.isInstance(constant)) { + throw new ClassCastException( + ("Illegal constant '" + + Pass2Verifier.getText(constant) + + "' at index '" + + value + + "'. '" + + Pass2Verifier.getText(node) + + "' expects a '" + + classValue + + "'.")); + } + } else { + throw new LoadingException( + ("Invalid index '" + value + "' used by '" + Pass2Verifier.getText(node) + "'.")); + } + } + + @Override + public void visitInnerClasses(InnerClasses innerClasses) { + this.checkIndex(innerClasses, innerClasses.getName_index(), this.CONST_Utf8); + String text; + if (!(text = ((ConstantUtf8) this.cp.getConstant(innerClasses.getName_index())).getBytes()) + .equals("InnerClasses")) { + throw new LoadingException( + ("The InnerClasses attribute '" + + Pass2Verifier.getText(innerClasses) + + "' is not correctly named 'InnerClasses' but '" + + text + + "'.")); + } + InnerClass[] innerClasses2 = innerClasses.getInnerClasses(); + int value; + for (int value2 = value = 0; value2 < innerClasses2.length; value2 = ++value) { + this.checkIndex(innerClasses, innerClasses2[value].getInner_class_index(), this.CONST_Class); + int value3; + if ((value3 = innerClasses2[value].getOuter_class_index()) != 0) { + this.checkIndex(innerClasses, value3, this.CONST_Class); + } + int value4; + if ((value4 = innerClasses2[value].getInner_name_index()) != 0) { + this.checkIndex(innerClasses, value4, this.CONST_Utf8); + } + if ((innerClasses2[value].getInner_access_flags() & -1568) != 0) { + this.this$0.addMessage( + "Unknown access flag for inner class '" + + Pass2Verifier.getText(innerClasses2[value]) + + "' set (InnerClasses attribute '" + + Pass2Verifier.getText(innerClasses) + + "')."); + } + } + } + + @Override + public void visitCode(Code code) { + JavaClass javaClass; + try { + this.checkIndex(code, code.getName_index(), this.CONST_Utf8); + String text; + if (!(text = ((ConstantUtf8) this.cp.getConstant(code.getName_index())).getBytes()) + .equals("Code")) { + throw new LoadingException( + ("The Code attribute '" + + Pass2Verifier.getText(code) + + "' is not correctly named 'Code' but '" + + text + + "'.")); + } + if (!(this.carrier.predecessor() instanceof Method)) { + this.this$0.addMessage( + "Code attribute '" + + Pass2Verifier.getText(code) + + "' is not declared in a method_info structure but in '" + + this.carrier.predecessor() + + "'. Ignored."); + } else { + Method method = (Method) this.carrier.predecessor(); + if (code.getCode().length == 0) { + throw new LoadingException( + ("Code array of Code attribute '" + + Pass2Verifier.getText(code) + + "' (method '" + + method + + "') must not be empty.")); + } + CodeException[] exceptionTable = code.getExceptionTable(); + int value; + for (int value2 = value = 0; value2 < exceptionTable.length; value2 = ++value) { + int value3; + if ((value3 = exceptionTable[value].getCatch_type()) != 0) { + this.checkIndex(code, value3, this.CONST_Class); + ConstantClass constantClass; + ConstantClass constantClass2 = + constantClass = (ConstantClass) this.cp.getConstant(value3); + this.checkIndex(constantClass2, constantClass2.getNameIndex(), this.CONST_Utf8); + String text2; + VerificationResult verificationResult; + if ((verificationResult = + VerifierFactory.getVerifier( + text2 = + ((ConstantUtf8) this.cp.getConstant(constantClass.getNameIndex())) + .getBytes() + .replace('/', '.')) + .createVerificationResult()) + != VerificationResult.VERIFICATION_RESULT2) { + throw new LoadingException( + ("Code attribute '" + + Pass2Verifier.getText(code) + + "' (method '" + + method + + "') has an exception_table entry '" + + Pass2Verifier.getText(exceptionTable[value]) + + "' that references '" + + text2 + + "' as an Exception but it does not pass verification pass 1: " + + verificationResult)); + } + JavaClass javaClass2 = Repository.lookupClass(text2); + JavaClass javaClass3 = Repository.lookupClass(Type.THROWABLE.getClassName()); + JavaClass javaClass4 = Repository.lookupClass(Type.OBJECT.getClassName()); + JavaClass javaClass5 = javaClass2; + while (true) { + if (javaClass5 == javaClass4) { + javaClass = javaClass2; + break; + } + if (javaClass2 == javaClass3) { + javaClass = javaClass2; + break; + } + VerificationResult verificationResult2; + if ((verificationResult2 = + VerifierFactory.getVerifier(javaClass2.getText5()).createVerificationResult()) + != VerificationResult.VERIFICATION_RESULT2) { + throw new LoadingException( + ("Code attribute '" + + Pass2Verifier.getText(code) + + "' (method '" + + method + + "') has an exception_table entry '" + + Pass2Verifier.getText(exceptionTable[value]) + + "' that references '" + + text2 + + "' as an Exception but '" + + javaClass2.getText5() + + "' in the ancestor hierachy does not pass verification pass 1: " + + verificationResult2)); + } + javaClass5 = javaClass2 = Repository.lookupClass(javaClass2.getText5()); + } + if (javaClass != javaClass3) { + throw new LoadingException( + ("Code attribute '" + + Pass2Verifier.getText(code) + + "' (method '" + + method + + "') has an exception_table entry '" + + Pass2Verifier.getText(exceptionTable[value]) + + "' that references '" + + text2 + + "' as an Exception but it is not a subclass of '" + + javaClass3.getText2() + + "'.")); + } + } + } + int value4 = -1; + Method[] methods = + Repository.lookupClass(Pass2Verifier.access$400(this.this$0).getClassName()) + .getMethods(); + int value5; + int value6 = value5 = 0; + while (true) { + if (value6 >= methods.length) { + value6 = value4; + break; + } + if (method == methods[value5]) { + value6 = value4 = value5; + break; + } + value6 = ++value5; + } + if (value6 < 0) { + throw new AssertionViolatedException( + "Could not find a known BCEL Method object in the corresponding BCEL JavaClass" + + " object."); + } + Pass2Verifier.access$500(this.this$0)[value4] = + new LocalVariablesInfo(code.getMax_locals()); + int value7 = 0; + Attribute[] attributes = code.getAttributes(); + for (int index = 0; index < attributes.length; index++) { + Attribute[] attributes2; + if (!(attributes[index] instanceof LineNumberTable) + && !(attributes[index] instanceof LocalVariableTable)) { + Pass2Verifier pass2Verifier = this.this$0; + StringBuilder stringBuilder = new StringBuilder().insert(0, "Attribute '"); + attributes2 = attributes; + pass2Verifier.addMessage( + stringBuilder + .append(Pass2Verifier.getText(attributes[index])) + .append("' as an attribute of Code attribute '") + .append(Pass2Verifier.getText(code)) + .append("' (method '") + .append(method) + .append("') is unknown and will therefore be ignored.") + .toString()); + } else { + this.this$0.addMessage( + "Attribute '" + + Pass2Verifier.getText(attributes[index]) + + "' as an attribute of Code attribute '" + + Pass2Verifier.getText(code) + + "' (method '" + + method + + "') will effectively be ignored and is only useful for debuggers and such."); + attributes2 = attributes; + } + if (attributes2[index] instanceof LocalVariableTable) { + LocalVariableTable localVariableTable; + LocalVariableTable localVariableTable2 = + localVariableTable = (LocalVariableTable) attributes[index]; + this.checkIndex( + localVariableTable2, localVariableTable2.getName_index(), this.CONST_Utf8); + String text3; + if (!(text3 = + ((ConstantUtf8) this.cp.getConstant(localVariableTable.getName_index())) + .getBytes()) + .equals("LocalVariableTable")) { + throw new LoadingException( + ("The LocalVariableTable attribute '" + + Pass2Verifier.getText(localVariableTable) + + "' is not correctly named 'LocalVariableTable' but '" + + text3 + + "'.")); + } + LocalVariable[] localVariableTable3 = localVariableTable.getLocalVariableTable(); + int value8; + for (value6 = value8 = 0; value6 < localVariableTable3.length; value6 = ++value8) { + this.checkIndex( + localVariableTable, localVariableTable3[value8].getName_index(), this.CONST_Utf8); + String text4; + if (!Pass2Verifier.matchesText4( + text4 = + ((ConstantUtf8) + this.cp.getConstant(localVariableTable3[value8].getName_index())) + .getBytes())) { + throw new LoadingException( + ("LocalVariableTable '" + + Pass2Verifier.getText(localVariableTable) + + "' references a local variable by the name '" + + text4 + + "' which is not a legal Java simple name.")); + } + this.checkIndex( + localVariableTable, + localVariableTable3[value8].getSignature_index(), + this.CONST_Utf8); + String bytes = + ((ConstantUtf8) + this.cp.getConstant(localVariableTable3[value8].getSignature_index())) + .getBytes(); + Type type; + try { + type = Type.getType(bytes); + } catch (ClassFormatException classFormatException) { + throw new LoadingException( + ("Illegal descriptor (==signature) '" + + bytes + + "' used by LocalVariable '" + + Pass2Verifier.getText(localVariableTable3[value8]) + + "' referenced by '" + + Pass2Verifier.getText(localVariableTable) + + "'.")); + } + int index2 = localVariableTable3[value8].getIndex(); + Code code2; + if (type != Type.LONG && type != Type.DOUBLE) { + value6 = index2; + code2 = code; + } else { + value6 = index2 + 1; + code2 = code; + } + if (value6 >= code2.getMax_locals()) { + throw new LoadingException( + ("LocalVariableTable attribute '" + + Pass2Verifier.getText(localVariableTable) + + "' references a LocalVariable '" + + Pass2Verifier.getText(localVariableTable3[value8]) + + "' with an index that exceeds the surrounding Code attribute's max_locals" + + " value of '" + + code.getMax_locals() + + "'.")); + } + try { + Pass2Verifier.access$500(this.this$0)[value4].add( + index2, + text4, + localVariableTable3[value8].getStart_pc(), + localVariableTable3[value8].getLength(), + type); + } catch (ClassConstraintException classConstraintException) { + throw new LoadingException( + ("Conflicting information in LocalVariableTable '" + + Pass2Verifier.getText(localVariableTable) + + "' found in Code attribute '" + + Pass2Verifier.getText(code) + + "' (method '" + + Pass2Verifier.getText(method) + + "'). " + + classConstraintException.getMessage())); + } + } + if (++value7 > code.getMax_locals()) { + throw new LoadingException( + ("Number of LocalVariableTable attributes of Code attribute '" + + Pass2Verifier.getText(code) + + "' (method '" + + Pass2Verifier.getText(method) + + "') exceeds number of local variable slots '" + + code.getMax_locals() + + "' ('There may be no more than one LocalVariableTable attribute per local" + + " variable in the Code attribute.').")); + } + } + } + } + } catch (ClassNotFoundException classNotFoundException) { + throw new AssertionViolatedException(("Missing class: " + classNotFoundException.toString())); + } + } + + @Override + public void visitConstantInterfaceMethodref( + ConstantInterfaceMethodref constantInterfaceMethodref) { + if (constantInterfaceMethodref.getTag() != 11) { + throw new LoadingException( + ("Wrong constant tag in '" + Pass2Verifier.getText(constantInterfaceMethodref) + "'.")); + } + this.checkIndex( + constantInterfaceMethodref, constantInterfaceMethodref.getClass_index(), this.CONST_Class); + this.checkIndex( + constantInterfaceMethodref, + constantInterfaceMethodref.getName_and_type_index(), + this.CONST_NameAndType); + } + + @Override + public void visitConstantMethodref(ConstantMethodref constantMethodref) { + if (constantMethodref.getTag() != 10) { + throw new LoadingException( + ("Wrong constant tag in '" + Pass2Verifier.getText(constantMethodref) + "'.")); + } + this.checkIndex(constantMethodref, constantMethodref.getClass_index(), this.CONST_Class); + this.checkIndex( + constantMethodref, constantMethodref.getName_and_type_index(), this.CONST_NameAndType); + } + + @Override + public void visitConstantClass(ConstantClass constantClass) { + if (constantClass.getTag() != 7) { + throw new LoadingException( + ("Wrong constant tag in '" + Pass2Verifier.getText(constantClass) + "'.")); + } + this.checkIndex(constantClass, constantClass.getNameIndex(), this.CONST_Utf8); + } + + @Override + public void visitConstantInteger(ConstantInteger constantInteger) { + if (constantInteger.getTag() != 3) { + throw new LoadingException( + ("Wrong constant tag in '" + Pass2Verifier.getText(constantInteger) + "'.")); + } + } + + @Override + public void visitConstantNameAndType(ConstantNameAndType constantNameAndType) { + if (constantNameAndType.getTag() != 12) { + throw new LoadingException( + ("Wrong constant tag in '" + Pass2Verifier.getText(constantNameAndType) + "'.")); + } + this.checkIndex(constantNameAndType, constantNameAndType.getName_index(), this.CONST_Utf8); + this.checkIndex(constantNameAndType, constantNameAndType.getSignature_index(), this.CONST_Utf8); + } + + @Override + public void visitDeprecated(Deprecated deprecated) { + this.checkIndex(deprecated, deprecated.getName_index(), this.CONST_Utf8); + String text; + if (!(text = ((ConstantUtf8) this.cp.getConstant(deprecated.getName_index())).getBytes()) + .equals("Deprecated")) { + throw new LoadingException( + ("The Deprecated attribute '" + + Pass2Verifier.getText(deprecated) + + "' is not correctly named 'Deprecated' but '" + + text + + "'.")); + } + } + + @Override + public void visitConstantLong(ConstantLong constantLong) { + if (constantLong.getTag() != 5) { + throw new LoadingException( + ("Wrong constant tag in '" + Pass2Verifier.getText(constantLong) + "'.")); + } + } + + @Override + public void visitConstantPool(ConstantPool constantPool) {} + + @Override + public void visitMethod(Method method) { + this.checkIndex(method, method.getCount3(), this.CONST_Utf8); + String text; + if (!Pass2Verifier.matchesEnabled2(text = method.getText(), true)) { + throw new LoadingException( + ("Method '" + Pass2Verifier.getText(method) + "' has illegal name '" + text + "'.")); + } + this.checkIndex(method, method.getCount(), this.CONST_Utf8); + String bytes = ((ConstantUtf8) this.cp.getConstant(method.getCount())).getBytes(); + Type[] types; + Type type; + try { + type = Type.getReturnType(bytes); + types = Type.getArgumentTypes(bytes); + } catch (ClassFormatException classFormatException) { + throw new LoadingException( + ("Illegal descriptor (==signature) '" + + bytes + + "' used by Method '" + + Pass2Verifier.getText(method) + + "'.")); + } + Type type2 = type; + if (type2 instanceof ArrayType) { + type2 = ((ArrayType) type2).getBasicType(); + } + VerificationResult verificationResult; + if (type2 instanceof ObjectType + && (verificationResult = + VerifierFactory.getVerifier(((ObjectType) type2).getClassName()) + .createVerificationResult()) + != VerificationResult.VERIFICATION_RESULT2) { + throw new LoadingException( + ("Method '" + + Pass2Verifier.getText(method) + + "' has a return type that does not pass verification pass 1: '" + + verificationResult + + "'.")); + } + int value; + for (int value2 = value = 0; value2 < types.length; value2 = ++value) { + Type type3; + if ((type3 = types[value]) instanceof ArrayType) { + type3 = ((ArrayType) type3).getBasicType(); + } + VerificationResult verificationResult2; + if (type3 instanceof ObjectType + && (verificationResult2 = + VerifierFactory.getVerifier(((ObjectType) type3).getClassName()) + .createVerificationResult()) + != VerificationResult.VERIFICATION_RESULT2) { + throw new LoadingException( + ("Method '" + + Pass2Verifier.getText(method) + + "' has an argument type that does not pass verification pass 1: '" + + verificationResult2 + + "'.")); + } + } + if (text.equals("") && types.length != 0) { + throw new LoadingException( + ("Method '" + + Pass2Verifier.getText(method) + + "' has illegal name '" + + text + + "'. It's name resembles the class or interface initialization method which it isn't" + + " because of its arguments (==descriptor).")); + } + if (this.jc.isEnabled17()) { + int value3 = 0; + if (method.isEnabled9()) { + value3++; + } + if (method.isEnabled13()) { + value3++; + } + if (method.isEnabled6()) { + value3++; + } + if (value3 > 1) { + throw new LoadingException( + ("Method '" + + Pass2Verifier.getText(method) + + "' must only have at most one of its ACC_PRIVATE, ACC_PROTECTED, ACC_PUBLIC" + + " modifiers set.")); + } + if (method.isEnabled15()) { + if (method.isEnabled3()) { + throw new LoadingException( + ("Abstract method '" + + Pass2Verifier.getText(method) + + "' must not have the ACC_FINAL modifier set.")); + } + if (method.isEnabled14()) { + throw new LoadingException( + ("Abstract method '" + + Pass2Verifier.getText(method) + + "' must not have the ACC_NATIVE modifier set.")); + } + if (method.isEnabled9()) { + throw new LoadingException( + ("Abstract method '" + + Pass2Verifier.getText(method) + + "' must not have the ACC_PRIVATE modifier set.")); + } + if (method.isEnabled11()) { + throw new LoadingException( + ("Abstract method '" + + Pass2Verifier.getText(method) + + "' must not have the ACC_STATIC modifier set.")); + } + if (method.isEnabled7()) { + throw new LoadingException( + ("Abstract method '" + + Pass2Verifier.getText(method) + + "' must not have the ACC_STRICT modifier set.")); + } + if (method.isEnabled12()) { + throw new LoadingException( + ("Abstract method '" + + Pass2Verifier.getText(method) + + "' must not have the ACC_SYNCHRONIZED modifier set.")); + } + } + } else if (!text.equals("")) { + if (!method.isEnabled6()) { + throw new LoadingException( + ("Interface method '" + + Pass2Verifier.getText(method) + + "' must have the ACC_PUBLIC modifier set but hasn't!")); + } + if (!method.isEnabled15()) { + throw new LoadingException( + ("Interface method '" + + Pass2Verifier.getText(method) + + "' must have the ACC_STATIC modifier set but hasn't!")); + } + if (method.isEnabled9() + || method.isEnabled13() + || method.isEnabled11() + || method.isEnabled3() + || method.isEnabled12() + || method.isEnabled14() + || method.isEnabled7()) { + throw new LoadingException( + ("Interface method '" + + Pass2Verifier.getText(method) + + "' must not have any of the ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL," + + " ACC_SYNCHRONIZED, ACC_NATIVE, ACC_ABSTRACT, ACC_STRICT modifiers set.")); + } + } + if (!text.equals("") + || !method.isEnabled11() + && !method.isEnabled3() + && !method.isEnabled12() + && !method.isEnabled14() + && !method.isEnabled15()) { + if (text.equals("")) { + if ((method.getAccess_flags2() & -2049) > 0) { + this.this$0.addMessage( + "Class or interface initialization method '" + + Pass2Verifier.getText(method) + + "' has superfluous access modifier(s) set: everything but ACC_STRICT is" + + " ignored."); + } + if (method.isEnabled15()) { + throw new LoadingException( + ("Class or interface initialization method '" + + Pass2Verifier.getText(method) + + "' must not be abstract. This contradicts the Java Language Specification," + + " Second Edition (which omits this constraint) but is common practice of" + + " existing verifiers.")); + } + } + if ((method.getAccess_flags2() & -3392) > 0) { + this.this$0.addMessage( + "Method '" + + Pass2Verifier.getText(method) + + "' has access flag(s) other than ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED," + + " ACC_STATIC, ACC_FINAL, ACC_SYNCHRONIZED, ACC_NATIVE, ACC_ABSTRACT, ACC_STRICT" + + " set (ignored)."); + } + String text2 = "" + text + bytes; + if (this.method_names_and_desc.contains(text2)) { + throw new LoadingException( + ("No two methods (like '" + + Pass2Verifier.getText(method) + + "') are allowed have same names and desciptors!")); + } + this.method_names_and_desc.add(text2); + Attribute[] attributes = method.getAttributes(); + int value4 = 0; + int value5 = 0; + for (int value6 = value5; value6 < attributes.length; value6 = ++value5) { + if (!(attributes[value5] instanceof Code) + && !(attributes[value5] instanceof ExceptionTable) + && !(attributes[value5] instanceof Synthetic) + && !(attributes[value5] instanceof Deprecated)) { + this.this$0.addMessage( + "Attribute '" + + Pass2Verifier.getText(attributes[value5]) + + "' as an attribute of Method '" + + Pass2Verifier.getText(method) + + "' is unknown and will therefore be ignored."); + } + if (!(attributes[value5] instanceof Code) + && !(attributes[value5] instanceof ExceptionTable)) { + this.this$0.addMessage( + "Attribute '" + + Pass2Verifier.getText(attributes[value5]) + + "' as an attribute of Method '" + + Pass2Verifier.getText(method) + + "' is neither Code nor Exceptions and is therefore only of use for debuggers" + + " and such."); + } + if (attributes[value5] instanceof Code && (method.isEnabled14() || method.isEnabled15())) { + throw new LoadingException( + ("Native or abstract methods like '" + + Pass2Verifier.getText(method) + + "' must not have a Code attribute like '" + + Pass2Verifier.getText(attributes[value5]) + + "'.")); + } + if (attributes[value5] instanceof Code) { + value4++; + } + } + if (!method.isEnabled14() && !method.isEnabled15() && value4 != 1) { + throw new LoadingException( + ("Non-native, non-abstract methods like '" + + Pass2Verifier.getText(method) + + "' must have exactly one Code attribute (found: " + + value4 + + ").")); + } + } else { + throw new LoadingException( + ("Instance initialization method '" + + Pass2Verifier.getText(method) + + "' must not have any of the ACC_STATIC, ACC_FINAL, ACC_SYNCHRONIZED, ACC_NATIVE," + + " ACC_ABSTRACT modifiers set.")); + } + } + + @Override + public void visitSourceFile(SourceFile sourceFile) { + this.checkIndex(sourceFile, sourceFile.getName_index(), this.CONST_Utf8); + String text; + if (!(text = ((ConstantUtf8) this.cp.getConstant(sourceFile.getName_index())).getBytes()) + .equals("SourceFile")) { + throw new LoadingException( + ("The SourceFile attribute '" + + Pass2Verifier.getText(sourceFile) + + "' is not correctly named 'SourceFile' but '" + + text + + "'.")); + } + this.checkIndex(sourceFile, sourceFile.getSourceFileIndex(), this.CONST_Utf8); + String text2; + String text3 = + text2 = ((ConstantUtf8) this.cp.getConstant(sourceFile.getSourceFileIndex())).getBytes(); + String text4 = text3.toLowerCase(Locale.ENGLISH); + if (text3.indexOf(47) != -1 + || text2.indexOf(92) != -1 + || text2.indexOf(58) != -1 + || text4.lastIndexOf(".java") == -1) { + this.this$0.addMessage( + "SourceFile attribute '" + + Pass2Verifier.getText(sourceFile) + + "' has a funny name: remember not to confuse certain parsers working on javap's" + + " output. Also, this name ('" + + text2 + + "') is considered an unqualified (simple) file name only."); + } + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/statics/Pass2Verifier$FAMRAV_Visitor.java b/src/main/java/com/allatori/lib/bcel/verifier/statics/Pass2Verifier$FAMRAV_Visitor.java new file mode 100644 index 0000000..ae520af --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/statics/Pass2Verifier$FAMRAV_Visitor.java @@ -0,0 +1,185 @@ +package com.allatori.lib.bcel.verifier.statics; + +import com.allatori.lib.bcel.classfile.ClassFormatException; +import com.allatori.lib.bcel.classfile.ConstantClass; +import com.allatori.lib.bcel.classfile.ConstantFieldref; +import com.allatori.lib.bcel.classfile.ConstantInterfaceMethodref; +import com.allatori.lib.bcel.classfile.ConstantMethodref; +import com.allatori.lib.bcel.classfile.ConstantNameAndType; +import com.allatori.lib.bcel.classfile.ConstantPool; +import com.allatori.lib.bcel.classfile.ConstantUtf8; +import com.allatori.lib.bcel.classfile.EmptyVisitor; +import com.allatori.lib.bcel.classfile.JavaClass; +import com.allatori.lib.bcel.classfile.Visitor; +import com.allatori.lib.bcel.generic.Type; +import com.allatori.lib.bcel.verifier.exc.LoadingException; + +public class Pass2Verifier$FAMRAV_Visitor extends EmptyVisitor implements Visitor { + + public final ConstantPool cp; + + public final Pass2Verifier this$0; + + public Pass2Verifier$FAMRAV_Visitor( + Pass2Verifier pass2Verifier, JavaClass javaClass, Pass2Verifier$1 pass2Verifier$1) { + this(pass2Verifier, javaClass); + } + + @Override + public void visitConstantFieldref(ConstantFieldref constantFieldref) { + if (constantFieldref.getTag() != 9) { + throw new LoadingException( + ("ConstantFieldref '" + Pass2Verifier.getText(constantFieldref) + "' has wrong tag!")); + } + int name_and_type_index = constantFieldref.getName_and_type_index(); + ConstantNameAndType constantNameAndType = + (ConstantNameAndType) this.cp.getConstant(name_and_type_index); + String text; + if (!Pass2Verifier.matchesText( + text = + ((ConstantUtf8) this.cp.getConstant(constantNameAndType.getName_index())).getBytes())) { + throw new LoadingException( + ("Invalid field name '" + + text + + "' referenced by '" + + Pass2Verifier.getText(constantFieldref) + + "'.")); + } + int class_index = constantFieldref.getClass_index(); + ConstantClass constantClass = (ConstantClass) this.cp.getConstant(class_index); + String text2; + if (!Pass2Verifier.matchesText2( + text2 = ((ConstantUtf8) this.cp.getConstant(constantClass.getNameIndex())).getBytes())) { + throw new LoadingException( + ("Illegal class name '" + + text2 + + "' used by '" + + Pass2Verifier.getText(constantFieldref) + + "'.")); + } + String bytes = + ((ConstantUtf8) this.cp.getConstant(constantNameAndType.getSignature_index())).getBytes(); + try { + Type.getType(bytes); + } catch (ClassFormatException classFormatException) { + throw new LoadingException( + ("Illegal descriptor (==signature) '" + + bytes + + "' used by '" + + Pass2Verifier.getText(constantFieldref) + + "'.")); + } + } + + @Override + public void visitConstantMethodref(ConstantMethodref constantMethodref) { + if (constantMethodref.getTag() != 10) { + throw new LoadingException( + ("ConstantMethodref '" + Pass2Verifier.getText(constantMethodref) + "' has wrong tag!")); + } + int name_and_type_index = constantMethodref.getName_and_type_index(); + ConstantNameAndType constantNameAndType = + (ConstantNameAndType) this.cp.getConstant(name_and_type_index); + String text; + if (!Pass2Verifier.matchesText3( + text = + ((ConstantUtf8) this.cp.getConstant(constantNameAndType.getName_index())).getBytes())) { + throw new LoadingException( + ("Invalid (non-interface) method name '" + + text + + "' referenced by '" + + Pass2Verifier.getText(constantMethodref) + + "'.")); + } + int class_index = constantMethodref.getClass_index(); + ConstantClass constantClass = (ConstantClass) this.cp.getConstant(class_index); + String text2; + if (!Pass2Verifier.matchesText2( + text2 = ((ConstantUtf8) this.cp.getConstant(constantClass.getNameIndex())).getBytes())) { + throw new LoadingException( + ("Illegal class name '" + + text2 + + "' used by '" + + Pass2Verifier.getText(constantMethodref) + + "'.")); + } + String bytes = + ((ConstantUtf8) this.cp.getConstant(constantNameAndType.getSignature_index())).getBytes(); + try { + Type returnType = Type.getReturnType(bytes); + if (text.equals("") && returnType != Type.VOID) { + throw new LoadingException("Instance initialization method must have VOID return type."); + } + } catch (ClassFormatException classFormatException) { + throw new LoadingException( + ("Illegal descriptor (==signature) '" + + bytes + + "' used by '" + + Pass2Verifier.getText(constantMethodref) + + "'.")); + } + } + + @Override + public void visitConstantInterfaceMethodref( + ConstantInterfaceMethodref constantInterfaceMethodref) { + if (constantInterfaceMethodref.getTag() != 11) { + throw new LoadingException( + ("ConstantInterfaceMethodref '" + + Pass2Verifier.getText(constantInterfaceMethodref) + + "' has wrong tag!")); + } + int name_and_type_index = constantInterfaceMethodref.getName_and_type_index(); + ConstantNameAndType constantNameAndType = + (ConstantNameAndType) this.cp.getConstant(name_and_type_index); + String text; + if (!Pass2Verifier.matchesText10( + text = + ((ConstantUtf8) this.cp.getConstant(constantNameAndType.getName_index())).getBytes())) { + throw new LoadingException( + ("Invalid (interface) method name '" + + text + + "' referenced by '" + + Pass2Verifier.getText(constantInterfaceMethodref) + + "'.")); + } + int class_index = constantInterfaceMethodref.getClass_index(); + ConstantClass constantClass = (ConstantClass) this.cp.getConstant(class_index); + String text2; + if (!Pass2Verifier.matchesText2( + text2 = ((ConstantUtf8) this.cp.getConstant(constantClass.getNameIndex())).getBytes())) { + throw new LoadingException( + ("Illegal class name '" + + text2 + + "' used by '" + + Pass2Verifier.getText(constantInterfaceMethodref) + + "'.")); + } + String bytes = + ((ConstantUtf8) this.cp.getConstant(constantNameAndType.getSignature_index())).getBytes(); + try { + Type returnType = Type.getReturnType(bytes); + if (text.equals("") && returnType != Type.VOID) { + this.this$0.addMessage( + "Class or interface initialization method '' usually has VOID return type" + + " instead of '" + + returnType + + "'. Note this is really not a requirement of The Java Virtual Machine" + + " Specification, Second Edition."); + } + } catch (ClassFormatException classFormatException) { + throw new LoadingException( + ("Illegal descriptor (==signature) '" + + bytes + + "' used by '" + + Pass2Verifier.getText(constantInterfaceMethodref) + + "'.")); + } + } + + public Pass2Verifier$FAMRAV_Visitor(Pass2Verifier pass2Verifier, JavaClass javaClass) { + super(); + this.this$0 = pass2Verifier; + this.cp = javaClass.getConstantPool(); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/statics/Pass2Verifier$InnerClassDetector.java b/src/main/java/com/allatori/lib/bcel/verifier/statics/Pass2Verifier$InnerClassDetector.java new file mode 100644 index 0000000..bf5f266 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/statics/Pass2Verifier$InnerClassDetector.java @@ -0,0 +1,41 @@ +package com.allatori.lib.bcel.verifier.statics; + +import com.allatori.lib.bcel.classfile.Constant; +import com.allatori.lib.bcel.classfile.ConstantClass; +import com.allatori.lib.bcel.classfile.ConstantPool; +import com.allatori.lib.bcel.classfile.ConstantUtf8; +import com.allatori.lib.bcel.classfile.DescendingVisitor; +import com.allatori.lib.bcel.classfile.EmptyVisitor; +import com.allatori.lib.bcel.classfile.JavaClass; + +public class Pass2Verifier$InnerClassDetector extends EmptyVisitor { + + public ConstantPool cp; + + public boolean hasInnerClass; + + public JavaClass jc; + + public boolean innerClassReferenced() { + return this.hasInnerClass; + } + + @Override + public void visitConstantClass(ConstantClass constantClass) { + Constant constant; + if ((constant = this.cp.getConstant(constantClass.getNameIndex())) instanceof ConstantUtf8) { + String bytes = ((ConstantUtf8) constant).getBytes(); + if (bytes.startsWith(this.jc.getText2().replace('.', '/') + "$")) { + this.hasInnerClass = true; + } + } + } + + public Pass2Verifier$InnerClassDetector(JavaClass javaClass) { + super(); + this.hasInnerClass = false; + this.jc = javaClass; + this.cp = this.jc.getConstantPool(); + new DescendingVisitor(this.jc, this).visit(); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/statics/Pass2Verifier.java b/src/main/java/com/allatori/lib/bcel/verifier/statics/Pass2Verifier.java new file mode 100644 index 0000000..d48ab94 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/statics/Pass2Verifier.java @@ -0,0 +1,258 @@ +package com.allatori.lib.bcel.verifier.statics; + +import com.allatori.lib.bcel.Constants; +import com.allatori.lib.bcel.Repository; +import com.allatori.lib.bcel.classfile.DescendingVisitor; +import com.allatori.lib.bcel.classfile.JavaClass; +import com.allatori.lib.bcel.classfile.Method; +import com.allatori.lib.bcel.classfile.Node; +import com.allatori.lib.bcel.generic.Type; +import com.allatori.lib.bcel.verifier.PassVerifier; +import com.allatori.lib.bcel.verifier.VerificationResult; +import com.allatori.lib.bcel.verifier.Verifier; +import com.allatori.lib.bcel.verifier.VerifierFactory; +import com.allatori.lib.bcel.verifier.exc.AssertionViolatedException; +import com.allatori.lib.bcel.verifier.exc.LoadingException; +import java.util.HashMap; +import java.util.HashSet; + +public final class Pass2Verifier extends PassVerifier implements Constants { + + public Verifier myOwner; + + public LocalVariablesInfo[] localVariablesInfos; + + public static Verifier access$400(Pass2Verifier pass2Verifier) { + return pass2Verifier.myOwner; + } + + public Pass2Verifier(Verifier verifier) { + super(); + this.myOwner = verifier; + } + + public static boolean matchesText(String text) { + return matchesText9(text); + } + + public static boolean matchesText2(String text) { + return matchesText8(text); + } + + public void final_methods_are_not_overridden() { + try { + HashMap entries = new HashMap(); + JavaClass javaClass = Repository.lookupClass(this.myOwner.getClassName()); + for (int value = -1; value != 0; javaClass = Repository.lookupClass(javaClass.getText5())) { + value = javaClass.getCount2(); + Method[] methods = javaClass.getMethods(); + int value2; + for (int value3 = value2 = 0; value3 < methods.length; value3 = ++value2) { + String text = "" + methods[value2].getText() + methods[value2].getText2(); + if (entries.containsKey(text)) { + if (methods[value2].isEnabled3()) { + if (!methods[value2].isEnabled9()) { + throw new LoadingException( + ("Method '" + + text + + "' in class '" + + entries.get(text) + + "' overrides the final (not-overridable) definition in class '" + + javaClass.getText2() + + "'.")); + } + this.addMessage( + "Method '" + + text + + "' in class '" + + entries.get(text) + + "' overrides the final (not-overridable) definition in class '" + + javaClass.getText2() + + "'. This is okay, as the original definition was private; however this" + + " constraint leverage was introduced by JLS 8.4.6 (not vmspec2) and the" + + " behaviour of the Sun verifiers."); + } else if (!methods[value2].isEnabled11()) { + entries.put(text, javaClass.getText2()); + } + } else if (!methods[value2].isEnabled11()) { + entries.put(text, javaClass.getText2()); + } + } + } + } catch (ClassNotFoundException classNotFoundException) { + throw new AssertionViolatedException(("Missing class: " + classNotFoundException.toString())); + } + } + + public static String getText(Node node) { + return createText(node); + } + + public static boolean matchesText3(String text) { + return matchesText5(text); + } + + public void every_class_has_an_accessible_superclass() { + try { + HashSet values = new HashSet(); + JavaClass javaClass = Repository.lookupClass(this.myOwner.getClassName()); + int value = -1; + while (value != 0) { + if ((value = javaClass.getCount2()) == 0) { + if (javaClass != Repository.lookupClass(Type.OBJECT.getClassName())) { + throw new LoadingException( + ("Superclass of '" + + javaClass.getText2() + + "' missing but not " + + Type.OBJECT.getClassName() + + " itself!")); + } + } else { + String text5 = javaClass.getText5(); + if (!values.add(text5)) { + throw new LoadingException("Circular superclass hierarchy detected."); + } + if (VerifierFactory.getVerifier(text5).createVerificationResult() + != VerificationResult.VERIFICATION_RESULT2) { + throw new LoadingException(("Could not load in ancestor class '" + text5 + "'.")); + } + if ((javaClass = Repository.lookupClass(text5)).isEnabled3()) { + throw new LoadingException( + ("Ancestor class '" + + text5 + + "' has the FINAL access modifier and must therefore not be subclassed.")); + } + } + } + } catch (ClassNotFoundException classNotFoundException) { + throw new AssertionViolatedException(("Missing class: " + classNotFoundException.toString())); + } + } + + public static String createText(Node node) { + return new StringRepresentation(node).toString(); + } + + public static boolean matchesText4(String text) { + return matchesText6(text); + } + + public static LocalVariablesInfo[] access$500(Pass2Verifier pass2Verifier) { + return pass2Verifier.localVariablesInfos; + } + + public static boolean matchesText5(String text) { + return matchesEnabled(text, false); + } + + public static boolean matchesText6(String text) { + if (text.length() == 0) { + return false; + } + if (!Character.isJavaIdentifierStart(text.charAt(0))) { + return false; + } + int value; + for (int value2 = value = 1; value2 < text.length(); value2 = ++value) { + if (!Character.isJavaIdentifierPart(text.charAt(value))) { + return false; + } + } + return true; + } + + public void constant_pool_entries_satisfy_static_constraints() { + try { + JavaClass javaClass = Repository.lookupClass(this.myOwner.getClassName()); + new Pass2Verifier$CPESSC_Visitor(this, javaClass, null); + } catch (ClassNotFoundException classNotFoundException) { + throw new AssertionViolatedException(("Missing class: " + classNotFoundException.toString())); + } + } + + @Override + public VerificationResult getVerificationResult() { + try { + if (this.myOwner.createVerificationResult().equals(VerificationResult.VERIFICATION_RESULT2)) { + this.localVariablesInfos = + new LocalVariablesInfo + [Repository.lookupClass(this.myOwner.getClassName()).getMethods().length]; + VerificationResult verificationResult = VerificationResult.VERIFICATION_RESULT2; + try { + this.constant_pool_entries_satisfy_static_constraints(); + this.field_and_method_refs_are_valid(); + this.every_class_has_an_accessible_superclass(); + this.final_methods_are_not_overridden(); + return verificationResult; + } catch (LoadingException loadingException) { + return new VerificationResult(2, loadingException.getMessage()); + } + } else { + return VerificationResult.VERIFICATION_RESULT; + } + } catch (ClassNotFoundException classNotFoundException) { + throw new AssertionViolatedException(("Missing class: " + classNotFoundException.toString())); + } + } + + public static boolean matchesEnabled(String text, boolean matches) { + if (matchesText7(text)) { + return true; + } else { + return matches ? text.equals("") || text.equals("") : text.equals(""); + } + } + + public static boolean matchesText7(String text) { + if (!Character.isJavaIdentifierStart(text.charAt(0))) { + return false; + } + int value; + for (int value2 = value = 1; value2 < text.length(); value2 = ++value) { + if (!Character.isJavaIdentifierPart(text.charAt(value))) { + return false; + } + } + return true; + } + + public void field_and_method_refs_are_valid() { + try { + JavaClass javaClass = Repository.lookupClass(this.myOwner.getClassName()); + new DescendingVisitor(javaClass, new Pass2Verifier$FAMRAV_Visitor(this, javaClass, null)) + .visit(); + } catch (ClassNotFoundException classNotFoundException) { + throw new AssertionViolatedException(("Missing class: " + classNotFoundException.toString())); + } + } + + public static final boolean matchesText8(String text) { + return true; + } + + public LocalVariablesInfo getLocalVariablesInfo(int value) { + if (this.getVerificationResult2() != VerificationResult.VERIFICATION_RESULT2) { + return null; + } else if (value >= 0 && value < this.localVariablesInfos.length) { + return this.localVariablesInfos[value]; + } else { + throw new AssertionViolatedException("Method number out of range."); + } + } + + public static boolean matchesEnabled2(String text, boolean matches) { + return matchesEnabled(text, matches); + } + + public static boolean matchesText9(String text) { + return matchesText6(text); + } + + public static boolean matchesText10(String text) { + return matchesText11(text); + } + + public static boolean matchesText11(String text) { + return text.startsWith("<") ? false : matchesText7(text); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/statics/Pass3aVerifier$InstOperandConstraintVisitor.java b/src/main/java/com/allatori/lib/bcel/verifier/statics/Pass3aVerifier$InstOperandConstraintVisitor.java new file mode 100644 index 0000000..2785714 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/statics/Pass3aVerifier$InstOperandConstraintVisitor.java @@ -0,0 +1,1016 @@ +package com.allatori.lib.bcel.verifier.statics; + +import com.allatori.lib.bcel.Repository; +import com.allatori.lib.bcel.classfile.Constant; +import com.allatori.lib.bcel.classfile.ConstantClass; +import com.allatori.lib.bcel.classfile.ConstantDouble; +import com.allatori.lib.bcel.classfile.ConstantFieldref; +import com.allatori.lib.bcel.classfile.ConstantFloat; +import com.allatori.lib.bcel.classfile.ConstantInteger; +import com.allatori.lib.bcel.classfile.ConstantInterfaceMethodref; +import com.allatori.lib.bcel.classfile.ConstantLong; +import com.allatori.lib.bcel.classfile.ConstantMethodref; +import com.allatori.lib.bcel.classfile.ConstantNameAndType; +import com.allatori.lib.bcel.classfile.ConstantString; +import com.allatori.lib.bcel.classfile.ConstantUtf8; +import com.allatori.lib.bcel.classfile.Field; +import com.allatori.lib.bcel.classfile.JavaClass; +import com.allatori.lib.bcel.classfile.Method; +import com.allatori.lib.bcel.generic.ALOAD; +import com.allatori.lib.bcel.generic.ANEWARRAY; +import com.allatori.lib.bcel.generic.ASTORE; +import com.allatori.lib.bcel.generic.ArrayType; +import com.allatori.lib.bcel.generic.CHECKCAST; +import com.allatori.lib.bcel.generic.ConstantPoolGen; +import com.allatori.lib.bcel.generic.DLOAD; +import com.allatori.lib.bcel.generic.DSTORE; +import com.allatori.lib.bcel.generic.EmptyVisitor; +import com.allatori.lib.bcel.generic.FLOAD; +import com.allatori.lib.bcel.generic.FSTORE; +import com.allatori.lib.bcel.generic.FieldInstruction; +import com.allatori.lib.bcel.generic.GETSTATIC; +import com.allatori.lib.bcel.generic.IINC; +import com.allatori.lib.bcel.generic.ILOAD; +import com.allatori.lib.bcel.generic.INSTANCEOF; +import com.allatori.lib.bcel.generic.INVOKEINTERFACE; +import com.allatori.lib.bcel.generic.INVOKESPECIAL; +import com.allatori.lib.bcel.generic.INVOKESTATIC; +import com.allatori.lib.bcel.generic.INVOKEVIRTUAL; +import com.allatori.lib.bcel.generic.ISTORE; +import com.allatori.lib.bcel.generic.Instruction; +import com.allatori.lib.bcel.generic.InvokeInstruction; +import com.allatori.lib.bcel.generic.LDC; +import com.allatori.lib.bcel.generic.LDC2_W; +import com.allatori.lib.bcel.generic.LLOAD; +import com.allatori.lib.bcel.generic.LOOKUPSWITCH; +import com.allatori.lib.bcel.generic.LSTORE; +import com.allatori.lib.bcel.generic.LoadClass; +import com.allatori.lib.bcel.generic.MULTIANEWARRAY; +import com.allatori.lib.bcel.generic.NEW; +import com.allatori.lib.bcel.generic.NEWARRAY; +import com.allatori.lib.bcel.generic.ObjectType; +import com.allatori.lib.bcel.generic.PUTSTATIC; +import com.allatori.lib.bcel.generic.RET; +import com.allatori.lib.bcel.generic.TABLESWITCH; +import com.allatori.lib.bcel.generic.Type; +import com.allatori.lib.bcel.verifier.VerificationResult; +import com.allatori.lib.bcel.verifier.VerifierFactory; +import com.allatori.lib.bcel.verifier.exc.AssertionViolatedException; +import com.allatori.lib.bcel.verifier.exc.StaticCodeInstructionConstraintException; + +public class Pass3aVerifier$InstOperandConstraintVisitor extends EmptyVisitor { + + public ConstantPoolGen constantPoolGen; + + public final Pass3aVerifier this$0; + + public Pass3aVerifier$InstOperandConstraintVisitor( + Pass3aVerifier pass3aVerifier, ConstantPoolGen constantPoolGen2) { + super(); + this.this$0 = pass3aVerifier; + this.constantPoolGen = constantPoolGen2; + } + + @Override + public void visitASTORE(ASTORE aSTORE) { + int value; + if ((value = aSTORE.getIndex()) < 0) { + this.constraintViolated(aSTORE, "Index '" + value + "' must be non-negative."); + } else { + int value2 = this.maxLocals() - 1; + if (value > value2) { + this.constraintViolated( + aSTORE, + "Index '" + value + "' must not be greater than max_locals-1 '" + value2 + "'."); + } + } + } + + @Override + public void visitLDC(LDC lDC) { + this.indexValid(lDC, lDC.getIndex()); + Constant constant; + if ((constant = this.constantPoolGen.getConstant(lDC.getIndex())) instanceof ConstantClass) { + this.this$0.addMessage( + "Operand of LDC or LDC_W is CONSTANT_Class '" + + constant + + "' - this is only supported in JDK 1.5 and higher."); + } else { + if (!(constant instanceof ConstantInteger) + && !(constant instanceof ConstantFloat) + && !(constant instanceof ConstantString)) { + this.constraintViolated( + lDC, + "Operand of LDC or LDC_W must be one of CONSTANT_Integer, CONSTANT_Float or" + + " CONSTANT_String, but is '" + + constant + + "'."); + } + } + } + + @Override + public void visitPUTSTATIC(PUTSTATIC pUTSTATIC) { + Field field; + try { + String fieldName = pUTSTATIC.getFieldName(this.constantPoolGen); + JavaClass javaClass; + Field[] fields = + (javaClass = + Repository.lookupClass( + pUTSTATIC.createObjectType(this.constantPoolGen).getClassName())) + .getFields(); + Field field2 = null; + int value; + int value2 = value = 0; + while (true) { + if (value2 >= fields.length) { + field = field2; + break; + } + if (fields[value].getText().equals(fieldName)) { + field = field2 = fields[value]; + break; + } + value2 = ++value; + } + if (field == null) { + throw new AssertionViolatedException("Field not found?!?"); + } + if (field2.isEnabled3() + && !Pass3aVerifier.access$000(this.this$0) + .getClassName() + .equals(pUTSTATIC.createObjectType(this.constantPoolGen).getClassName())) { + this.constraintViolated( + pUTSTATIC, + "Referenced field '" + + field2 + + "' is final and must therefore be declared in the current class '" + + Pass3aVerifier.access$000(this.this$0).getClassName() + + "' which is not the case: it is declared in '" + + pUTSTATIC.createObjectType(this.constantPoolGen).getClassName() + + "'."); + } + if (!field2.isEnabled11()) { + this.constraintViolated( + pUTSTATIC, "Referenced field '" + field2 + "' is not static which it should be."); + } + String text = + Repository.lookupClass(Pass3aVerifier.access$000(this.this$0).getClassName()) + .getMethods()[Pass3aVerifier.access$100(this.this$0)] + .getText(); + if (!javaClass.isEnabled17() && !text.equals("")) { + this.constraintViolated( + pUTSTATIC, + "Interface field '" + field2 + "' must be set in a '" + "" + "' method."); + } + } catch (ClassNotFoundException classNotFoundException) { + throw new AssertionViolatedException(("Missing class: " + classNotFoundException.toString())); + } + } + + @Override + public void visitTABLESWITCH(TABLESWITCH tABLESWITCH) {} + + @Override + public void visitDLOAD(DLOAD dLOAD) { + int value; + if ((value = dLOAD.getIndex()) < 0) { + this.constraintViolated( + dLOAD, + "Index '" + + value + + "' must be non-negative. [Constraint by JustIce as an analogon to the single-slot" + + " xLOAD/xSTORE instructions; may not happen anyway.]"); + } else { + int value2 = this.maxLocals() - 2; + if (value > value2) { + this.constraintViolated( + dLOAD, "Index '" + value + "' must not be greater than max_locals-2 '" + value2 + "'."); + } + } + } + + @Override + public void visitMULTIANEWARRAY(MULTIANEWARRAY mULTIANEWARRAY) { + this.indexValid(mULTIANEWARRAY, mULTIANEWARRAY.getIndex()); + Constant constant; + if (!((constant = this.constantPoolGen.getConstant(mULTIANEWARRAY.getIndex())) + instanceof ConstantClass)) { + this.constraintViolated( + mULTIANEWARRAY, "Expecting a CONSTANT_Class operand, but found a '" + constant + "'."); + } + short value; + if ((value = mULTIANEWARRAY.getDimensions()) < 1) { + this.constraintViolated( + mULTIANEWARRAY, "Number of dimensions to create must be greater than zero."); + } + Type type; + if ((type = mULTIANEWARRAY.getType(this.constantPoolGen)) instanceof ArrayType) { + if (((ArrayType) type).getDimensions() < value) { + this.constraintViolated( + mULTIANEWARRAY, + "Not allowed to create array with more dimensions ('+dimensions2create+') than the one" + + " referenced by the CONSTANT_Class '" + + type + + "'."); + return; + } + } else { + this.constraintViolated( + mULTIANEWARRAY, + "Expecting a CONSTANT_Class referencing an array type. [Constraint not found in The Java" + + " Virtual Machine Specification, Second Edition, 4.8.1]"); + } + } + + @Override + public void visitInvokeInstruction(InvokeInstruction invokeInstruction) { + this.indexValid(invokeInstruction, invokeInstruction.getIndex()); + if (!(invokeInstruction instanceof INVOKEVIRTUAL) + && !(invokeInstruction instanceof INVOKESPECIAL) + && !(invokeInstruction instanceof INVOKESTATIC)) { + Constant constant; + if (!((constant = this.constantPoolGen.getConstant(invokeInstruction.getIndex())) + instanceof ConstantInterfaceMethodref)) { + this.constraintViolated( + invokeInstruction, + "Indexing a constant that's not a CONSTANT_InterfaceMethodref but a '" + + constant + + "'."); + } + ConstantNameAndType constantNameAndType = + (ConstantNameAndType) + this.constantPoolGen.getConstant( + ((ConstantInterfaceMethodref) constant).getName_and_type_index()); + String text; + if ((text = + ((ConstantUtf8) this.constantPoolGen.getConstant(constantNameAndType.getName_index())) + .getBytes()) + .equals("")) { + this.constraintViolated(invokeInstruction, "Method to invoke must not be ''."); + } + if (text.equals("")) { + this.constraintViolated(invokeInstruction, "Method to invoke must not be ''."); + } + } else { + Constant constant2; + if (!((constant2 = this.constantPoolGen.getConstant(invokeInstruction.getIndex())) + instanceof ConstantMethodref)) { + this.constraintViolated( + invokeInstruction, + "Indexing a constant that's not a CONSTANT_Methodref but a '" + constant2 + "'."); + } else { + ConstantNameAndType constantNameAndType2 = + (ConstantNameAndType) + this.constantPoolGen.getConstant( + ((ConstantMethodref) constant2).getName_and_type_index()); + ConstantUtf8 constantUtf8; + if ((constantUtf8 = + (ConstantUtf8) + this.constantPoolGen.getConstant(constantNameAndType2.getName_index())) + .getBytes() + .equals("") + && !(invokeInstruction instanceof INVOKESPECIAL)) { + this.constraintViolated( + invokeInstruction, + "Only INVOKESPECIAL is allowed to invoke instance initialization methods."); + } + if (!constantUtf8.getBytes().equals("") && constantUtf8.getBytes().startsWith("<")) { + this.constraintViolated( + invokeInstruction, + "No method with a name beginning with '<' other than the instance initialization" + + " methods may be called by the method invocation instructions."); + } + } + } + Type type; + if ((type = invokeInstruction.getType2(this.constantPoolGen)) instanceof ArrayType) { + type = ((ArrayType) type).getBasicType(); + } + VerificationResult verificationResult; + if (type instanceof ObjectType + && (verificationResult = + VerifierFactory.getVerifier(((ObjectType) type).getClassName()) + .createVerificationResult2()) + .getStatus() + != 1) { + this.constraintViolated( + invokeInstruction, + "Return type class/interface could not be verified successfully: '" + + verificationResult.getDetailMessage() + + "'."); + } + Type[] argumentTypes = invokeInstruction.getArgumentTypes(this.constantPoolGen); + int value; + for (int value2 = value = 0; value2 < argumentTypes.length; value2 = ++value) { + Type type2; + if ((type2 = argumentTypes[value]) instanceof ArrayType) { + type2 = ((ArrayType) type2).getBasicType(); + } + VerificationResult verificationResult2; + if (type2 instanceof ObjectType + && (verificationResult2 = + VerifierFactory.getVerifier(((ObjectType) type2).getClassName()) + .createVerificationResult2()) + .getStatus() + != 1) { + this.constraintViolated( + invokeInstruction, + "Argument type class/interface could not be verified successfully: '" + + verificationResult2.getDetailMessage() + + "'."); + } + } + } + + @Override + public void visitFSTORE(FSTORE fSTORE) { + int value; + if ((value = fSTORE.getIndex()) < 0) { + this.constraintViolated(fSTORE, "Index '" + value + "' must be non-negative."); + } else { + int value2 = this.maxLocals() - 1; + if (value > value2) { + this.constraintViolated( + fSTORE, + "Index '" + value + "' must not be greater than max_locals-1 '" + value2 + "'."); + } + } + } + + public void constraintViolated(Instruction instruction, String text) { + throw new StaticCodeInstructionConstraintException( + ("Instruction " + instruction + " constraint violated: " + text)); + } + + @Override + public void visitINSTANCEOF(INSTANCEOF nSTANCEOF) { + this.indexValid(nSTANCEOF, nSTANCEOF.getIndex()); + Constant constant; + if (!((constant = this.constantPoolGen.getConstant(nSTANCEOF.getIndex())) + instanceof ConstantClass)) { + this.constraintViolated( + nSTANCEOF, "Expecting a CONSTANT_Class operand, but found a '" + constant + "'."); + } + } + + @Override + public void visitFieldInstruction(FieldInstruction fieldInstruction) { + Field field; + Field field2; + try { + this.indexValid(fieldInstruction, fieldInstruction.getIndex()); + Constant constant; + if (!((constant = this.constantPoolGen.getConstant(fieldInstruction.getIndex())) + instanceof ConstantFieldref)) { + this.constraintViolated( + fieldInstruction, + "Indexing a constant that's not a CONSTANT_Fieldref but a '" + constant + "'."); + } + String fieldName = fieldInstruction.getFieldName(this.constantPoolGen); + JavaClass javaClass; + Field[] fields = + (javaClass = + Repository.lookupClass( + fieldInstruction.createObjectType(this.constantPoolGen).getClassName())) + .getFields(); + Field field3 = null; + int value; + int value2 = value = 0; + while (true) { + if (value2 >= fields.length) { + field2 = field3; + break; + } + if (fields[value].getText().equals(fieldName)) { + Type type = Type.getType(fields[value].getText2()); + Type type2 = fieldInstruction.getType(this.constantPoolGen); + if (type.equals(type2)) { + field2 = field3 = fields[value]; + break; + } + } + value2 = ++value; + } + if (field2 != null) { + Type.getType(field3.getText2()); + fieldInstruction.getType(this.constantPoolGen); + } else { + JavaClass[] javaClasss = javaClass.createJavaClasss(); + int value3; + value2 = value3 = 0; + label52: + while (true) { + if (value2 < javaClasss.length) { + Field[] fields2 = javaClasss[value3].getFields(); + int value4; + value2 = value4 = 0; + while (true) { + if (value2 >= fields2.length) { + value2 = ++value3; + continue label52; + } + if (fields2[value4].getText().equals(fieldName)) { + Type type3 = Type.getType(fields2[value4].getText2()); + Type type4 = fieldInstruction.getType(this.constantPoolGen); + if (type3.equals(type4)) { + if (((field3 = fields2[value4]).getAccess_flags2() & 5) == 0) { + field = null; + break label52; + } + break; + } + } + value2 = ++value4; + } + } + field = field3; + break; + } + if (field == null) { + this.constraintViolated( + fieldInstruction, + "Referenced field '" + + fieldName + + "' does not exist in class '" + + javaClass.getText2() + + "'."); + } + } + } catch (ClassNotFoundException classNotFoundException) { + throw new AssertionViolatedException(("Missing class: " + classNotFoundException.toString())); + } + } + + @Override + public void visitILOAD(ILOAD lOAD) { + int value; + if ((value = lOAD.getIndex()) < 0) { + this.constraintViolated(lOAD, "Index '" + value + "' must be non-negative."); + } else { + int value2 = this.maxLocals() - 1; + if (value > value2) { + this.constraintViolated( + lOAD, "Index '" + value + "' must not be greater than max_locals-1 '" + value2 + "'."); + } + } + } + + @Override + public void visitLoadClass(LoadClass loadClass) { + ObjectType objectType; + VerificationResult verificationResult; + if ((objectType = loadClass.getLoadClassType(this.constantPoolGen)) != null + && (verificationResult = + VerifierFactory.getVerifier(objectType.getClassName()) + .createVerificationResult()) + .getStatus() + != 1) { + this.constraintViolated( + (Instruction) loadClass, + "Class '" + + loadClass.getLoadClassType(this.constantPoolGen).getClassName() + + "' is referenced, but cannot be loaded: '" + + verificationResult + + "'."); + } + } + + public boolean matchesValues(Object[] results, Object[] results2) { + if (results.length != results2.length) { + return false; + } + int value; + for (int value2 = value = 0; value2 < results.length; value2 = ++value) { + if (!results[value].equals(results2[value])) { + return false; + } + } + return true; + } + + @Override + public void visitNEWARRAY(NEWARRAY nEWARRAY) { + byte value; + if ((value = nEWARRAY.getTypecode()) != 4 + && value != 5 + && value != 6 + && value != 7 + && value != 8 + && value != 9 + && value != 10 + && value != 11) { + this.constraintViolated(nEWARRAY, "Illegal type code '+t+' for 'atype' operand."); + } + } + + @Override + public void visitLDC2_W(LDC2_W lDC2_W) { + this.indexValid(lDC2_W, lDC2_W.getIndex()); + Constant constant; + if (!((constant = this.constantPoolGen.getConstant(lDC2_W.getIndex())) instanceof ConstantLong) + && !(constant instanceof ConstantDouble)) { + this.constraintViolated( + lDC2_W, + "Operand of LDC2_W must be CONSTANT_Long or CONSTANT_Double, but is '" + constant + "'."); + } + try { + this.indexValid(lDC2_W, lDC2_W.getIndex() + 1); + } catch (StaticCodeInstructionConstraintException staticCodeInstructionConstraintException) { + throw new AssertionViolatedException( + "OOPS: Does not BCEL handle that? LDC2_W operand has a problem."); + } + } + + @Override + public void visitRET(RET rET) { + int value; + if ((value = rET.getIndex()) < 0) { + this.constraintViolated(rET, "Index '" + value + "' must be non-negative."); + } else { + int value2 = this.maxLocals() - 1; + if (value > value2) { + this.constraintViolated( + rET, "Index '" + value + "' must not be greater than max_locals-1 '" + value2 + "'."); + } + } + } + + @Override + public void visitLLOAD(LLOAD lLOAD) { + int value; + if ((value = lLOAD.getIndex()) < 0) { + this.constraintViolated( + lLOAD, + "Index '" + + value + + "' must be non-negative. [Constraint by JustIce as an analogon to the single-slot" + + " xLOAD/xSTORE instructions; may not happen anyway.]"); + } else { + int value2 = this.maxLocals() - 2; + if (value > value2) { + this.constraintViolated( + lLOAD, "Index '" + value + "' must not be greater than max_locals-2 '" + value2 + "'."); + } + } + } + + @Override + public void visitINVOKEVIRTUAL(INVOKEVIRTUAL nVOKEVIRTUAL) { + Method method; + try { + JavaClass javaClass; + Method[] methods = + (javaClass = Repository.lookupClass(nVOKEVIRTUAL.getText2(this.constantPoolGen))) + .getMethods(); + int value; + int value2 = value = 0; + while (true) { + if (value2 >= methods.length) { + method = (Method) (Object) null; + break; + } + if (methods[value].getText().equals(nVOKEVIRTUAL.getText4(this.constantPoolGen)) + && Type.getReturnType(methods[value].getText2()) + .equals(nVOKEVIRTUAL.getType2(this.constantPoolGen)) + && this.matchesValues( + Type.getArgumentTypes(methods[value].getText2()), + nVOKEVIRTUAL.getArgumentTypes(this.constantPoolGen))) { + method = methods[value]; + break; + } + value2 = ++value; + } + if (method == null) { + this.constraintViolated( + nVOKEVIRTUAL, + "Referenced method '" + + nVOKEVIRTUAL.getText4(this.constantPoolGen) + + "' with expected signature '" + + nVOKEVIRTUAL.getText3(this.constantPoolGen) + + "' not found in class '" + + javaClass.getText2() + + "'. The native verifier does allow the method to be declared in some superclass" + + " or implemented interface, which the Java Virtual Machine Specification, Second" + + " Edition does not."); + } + if (!javaClass.isEnabled17()) { + this.constraintViolated( + nVOKEVIRTUAL, + "Referenced class '" + + javaClass.getText2() + + "' is an interface, but not a class as expected."); + } + } catch (ClassNotFoundException classNotFoundException) { + throw new AssertionViolatedException(("Missing class: " + classNotFoundException.toString())); + } + } + + @Override + public void visitLSTORE(LSTORE lSTORE) { + int value; + if ((value = lSTORE.getIndex()) < 0) { + this.constraintViolated( + lSTORE, + "Index '" + + value + + "' must be non-negative. [Constraint by JustIce as an analogon to the single-slot" + + " xLOAD/xSTORE instructions; may not happen anyway.]"); + } else { + int value2 = this.maxLocals() - 2; + if (value > value2) { + this.constraintViolated( + lSTORE, + "Index '" + value + "' must not be greater than max_locals-2 '" + value2 + "'."); + } + } + } + + @Override + public void visitIINC(IINC iNC) { + int value; + if ((value = iNC.getIndex()) < 0) { + this.constraintViolated(iNC, "Index '" + value + "' must be non-negative."); + } else { + int value2 = this.maxLocals() - 1; + if (value > value2) { + this.constraintViolated( + iNC, "Index '" + value + "' must not be greater than max_locals-1 '" + value2 + "'."); + } + } + } + + @Override + public void visitANEWARRAY(ANEWARRAY aNEWARRAY) { + this.indexValid(aNEWARRAY, aNEWARRAY.getIndex()); + Constant constant; + if (!((constant = this.constantPoolGen.getConstant(aNEWARRAY.getIndex())) + instanceof ConstantClass)) { + this.constraintViolated( + aNEWARRAY, "Expecting a CONSTANT_Class operand, but found a '" + constant + "'."); + } + Type type; + if ((type = aNEWARRAY.getType(this.constantPoolGen)) instanceof ArrayType + && ((ArrayType) type).getDimensions() >= 255) { + this.constraintViolated( + aNEWARRAY, "Not allowed to create an array with more than 255 dimensions."); + } + } + + @Override + public void visitNEW(NEW nEW) { + this.indexValid(nEW, nEW.getIndex()); + Constant constant; + if (!((constant = this.constantPoolGen.getConstant(nEW.getIndex())) instanceof ConstantClass)) { + this.constraintViolated( + nEW, "Expecting a CONSTANT_Class operand, but found a '" + constant + "'."); + } else { + ConstantUtf8 constantUtf8 = + (ConstantUtf8) + this.constantPoolGen.getConstant(((ConstantClass) constant).getNameIndex()); + if (Type.getType("L" + constantUtf8.getBytes() + ";") instanceof ArrayType) { + this.constraintViolated(nEW, "NEW must not be used to create an array."); + } + } + } + + @Override + public void visitDSTORE(DSTORE dSTORE) { + int value; + if ((value = dSTORE.getIndex()) < 0) { + this.constraintViolated( + dSTORE, + "Index '" + + value + + "' must be non-negative. [Constraint by JustIce as an analogon to the single-slot" + + " xLOAD/xSTORE instructions; may not happen anyway.]"); + } else { + int value2 = this.maxLocals() - 2; + if (value > value2) { + this.constraintViolated( + dSTORE, + "Index '" + value + "' must not be greater than max_locals-2 '" + value2 + "'."); + } + } + } + + @Override + public void visitLOOKUPSWITCH(LOOKUPSWITCH lOOKUPSWITCH) { + int[] match = lOOKUPSWITCH.getMatch(); + int value = Integer.MIN_VALUE; + int value2; + for (int value3 = value2 = 0; value3 < match.length; value3 = ++value2) { + if (match[value2] == value && value2 != 0) { + this.constraintViolated( + lOOKUPSWITCH, "Match '" + match[value2] + "' occurs more than once."); + } + if (match[value2] < value) { + this.constraintViolated(lOOKUPSWITCH, "Lookup table must be sorted but isn't."); + } else { + value = match[value2]; + } + } + } + + @Override + public void visitCHECKCAST(CHECKCAST cHECKCAST) { + this.indexValid(cHECKCAST, cHECKCAST.getIndex()); + Constant constant; + if (!((constant = this.constantPoolGen.getConstant(cHECKCAST.getIndex())) + instanceof ConstantClass)) { + this.constraintViolated( + cHECKCAST, "Expecting a CONSTANT_Class operand, but found a '" + constant + "'."); + } + } + + public void indexValid(Instruction instruction, int value) { + if (value < 0 || value >= this.constantPoolGen.getSize()) { + this.constraintViolated(instruction, "Illegal constant pool index '" + value + "'."); + } + } + + @Override + public void visitINVOKESPECIAL(INVOKESPECIAL nVOKESPECIAL) { + Method method; + Method method2; + Method method3; + try { + JavaClass javaClass; + Method[] methods = + (javaClass = Repository.lookupClass(nVOKESPECIAL.getText2(this.constantPoolGen))) + .getMethods(); + int value; + int value2 = value = 0; + while (true) { + if (value2 >= methods.length) { + method3 = (Method) (Object) null; + break; + } + if (methods[value].getText().equals(nVOKESPECIAL.getText4(this.constantPoolGen)) + && Type.getReturnType(methods[value].getText2()) + .equals(nVOKESPECIAL.getType2(this.constantPoolGen)) + && this.matchesValues( + Type.getArgumentTypes(methods[value].getText2()), + nVOKESPECIAL.getArgumentTypes(this.constantPoolGen))) { + method3 = methods[value]; + break; + } + value2 = ++value; + } + if (method3 == null) { + this.constraintViolated( + nVOKESPECIAL, + "Referenced method '" + + nVOKESPECIAL.getText4(this.constantPoolGen) + + "' with expected signature '" + + nVOKESPECIAL.getText3(this.constantPoolGen) + + "' not found in class '" + + javaClass.getText2() + + "'. The native verifier does allow the method to be declared in some superclass" + + " or implemented interface, which the Java Virtual Machine Specification, Second" + + " Edition does not."); + } + JavaClass javaClass2; + if ((javaClass2 = + Repository.lookupClass(Pass3aVerifier.access$000(this.this$0).getClassName())) + .isEnabled16() + && Repository.matchesJavaClass(javaClass2, javaClass) + && !javaClass2.equals(javaClass) + && !nVOKESPECIAL.getText4(this.constantPoolGen).equals("")) { + int value3 = -1; + Method method4 = null; + while (true) { + if (value3 == 0) { + method2 = method4; + break; + } + value3 = javaClass2.getCount2(); + Method[] methods2 = + (javaClass2 = Repository.lookupClass(javaClass2.getText5())).getMethods(); + int value4; + value2 = value4 = 0; + while (true) { + if (value2 >= methods2.length) { + method = method4; + break; + } + if (methods2[value4].getText().equals(nVOKESPECIAL.getText4(this.constantPoolGen)) + && Type.getReturnType(methods2[value4].getText2()) + .equals(nVOKESPECIAL.getType2(this.constantPoolGen)) + && this.matchesValues( + Type.getArgumentTypes(methods2[value4].getText2()), + nVOKESPECIAL.getArgumentTypes(this.constantPoolGen))) { + method = method4 = methods2[value4]; + break; + } + value2 = ++value4; + } + if (method != null) { + method2 = method4; + break; + } + } + if (method2 == null) { + this.constraintViolated( + nVOKESPECIAL, + "ACC_SUPER special lookup procedure not successful: method '" + + nVOKESPECIAL.getText4(this.constantPoolGen) + + "' with proper signature not declared in superclass hierarchy."); + return; + } + } + } catch (ClassNotFoundException classNotFoundException) { + throw new AssertionViolatedException(("Missing class: " + classNotFoundException.toString())); + } + } + + @Override + public void visitFLOAD(FLOAD fLOAD) { + int value; + if ((value = fLOAD.getIndex()) < 0) { + this.constraintViolated(fLOAD, "Index '" + value + "' must be non-negative."); + } else { + int value2 = this.maxLocals() - 1; + if (value > value2) { + this.constraintViolated( + fLOAD, "Index '" + value + "' must not be greater than max_locals-1 '" + value2 + "'."); + } + } + } + + @Override + public void visitISTORE(ISTORE sTORE) { + int value; + if ((value = sTORE.getIndex()) < 0) { + this.constraintViolated(sTORE, "Index '" + value + "' must be non-negative."); + } else { + int value2 = this.maxLocals() - 1; + if (value > value2) { + this.constraintViolated( + sTORE, "Index '" + value + "' must not be greater than max_locals-1 '" + value2 + "'."); + } + } + } + + public int maxLocals() { + try { + return Repository.lookupClass(Pass3aVerifier.access$000(this.this$0).getClassName()) + .getMethods()[Pass3aVerifier.access$100(this.this$0)] + .getCode() + .getMax_locals(); + } catch (ClassNotFoundException classNotFoundException) { + throw new AssertionViolatedException(("Missing class: " + classNotFoundException.toString())); + } + } + + @Override + public void visitGETSTATIC(GETSTATIC gETSTATIC) { + Field field; + try { + String fieldName = gETSTATIC.getFieldName(this.constantPoolGen); + Field[] fields = + Repository.lookupClass(gETSTATIC.createObjectType(this.constantPoolGen).getClassName()) + .getFields(); + Field field2 = null; + int value; + int value2 = value = 0; + while (true) { + if (value2 >= fields.length) { + field = field2; + break; + } + if (fields[value].getText().equals(fieldName)) { + field = field2 = fields[value]; + break; + } + value2 = ++value; + } + if (field == null) { + throw new AssertionViolatedException("Field not found?!?"); + } + if (!field2.isEnabled11()) { + this.constraintViolated( + gETSTATIC, "Referenced field '" + field2 + "' is not static which it should be."); + } + } catch (ClassNotFoundException classNotFoundException) { + throw new AssertionViolatedException(("Missing class: " + classNotFoundException.toString())); + } + } + + @Override + public void visitALOAD(ALOAD aLOAD) { + int value; + if ((value = aLOAD.getIndex()) < 0) { + this.constraintViolated(aLOAD, "Index '" + value + "' must be non-negative."); + } else { + int value2 = this.maxLocals() - 1; + if (value > value2) { + this.constraintViolated( + aLOAD, "Index '" + value + "' must not be greater than max_locals-1 '" + value2 + "'."); + } + } + } + + @Override + public void visitINVOKEINTERFACE(INVOKEINTERFACE nVOKEINTERFACE) { + Method method; + try { + JavaClass javaClass; + Method[] methods = + (javaClass = Repository.lookupClass(nVOKEINTERFACE.getText2(this.constantPoolGen))) + .getMethods(); + int value; + int value2 = value = 0; + while (true) { + if (value2 >= methods.length) { + method = (Method) (Object) null; + break; + } + if (methods[value].getText().equals(nVOKEINTERFACE.getText4(this.constantPoolGen)) + && Type.getReturnType(methods[value].getText2()) + .equals(nVOKEINTERFACE.getType2(this.constantPoolGen)) + && this.matchesValues( + Type.getArgumentTypes(methods[value].getText2()), + nVOKEINTERFACE.getArgumentTypes(this.constantPoolGen))) { + method = methods[value]; + break; + } + value2 = ++value; + } + if (method == null) { + this.constraintViolated( + nVOKEINTERFACE, + "Referenced method '" + + nVOKEINTERFACE.getText4(this.constantPoolGen) + + "' with expected signature '" + + nVOKEINTERFACE.getText3(this.constantPoolGen) + + "' not found in class '" + + javaClass.getText2() + + "'. The native verifier does allow the method to be declared in some" + + " superinterface, which the Java Virtual Machine Specification, Second Edition" + + " does not."); + } + if (javaClass.isEnabled17()) { + this.constraintViolated( + nVOKEINTERFACE, + "Referenced class '" + + javaClass.getText2() + + "' is a class, but not an interface as expected."); + } + } catch (ClassNotFoundException classNotFoundException) { + throw new AssertionViolatedException(("Missing class: " + classNotFoundException.toString())); + } + } + + @Override + public void visitINVOKESTATIC(INVOKESTATIC nVOKESTATIC) { + Method method; + try { + JavaClass javaClass; + Method[] methods = + (javaClass = Repository.lookupClass(nVOKESTATIC.getText2(this.constantPoolGen))) + .getMethods(); + Method method2 = null; + int value; + int value2 = value = 0; + while (true) { + if (value2 >= methods.length) { + method = method2; + break; + } + if (methods[value].getText().equals(nVOKESTATIC.getText4(this.constantPoolGen)) + && Type.getReturnType(methods[value].getText2()) + .equals(nVOKESTATIC.getType2(this.constantPoolGen)) + && this.matchesValues( + Type.getArgumentTypes(methods[value].getText2()), + nVOKESTATIC.getArgumentTypes(this.constantPoolGen))) { + method = method2 = methods[value]; + break; + } + value2 = ++value; + } + if (method == null) { + this.constraintViolated( + nVOKESTATIC, + "Referenced method '" + + nVOKESTATIC.getText4(this.constantPoolGen) + + "' with expected signature '" + + nVOKESTATIC.getText3(this.constantPoolGen) + + "' not found in class '" + + javaClass.getText2() + + "'. The native verifier possibly allows the method to be declared in some" + + " superclass or implemented interface, which the Java Virtual Machine" + + " Specification, Second Edition does not."); + } else if (!method2.isEnabled11()) { + this.constraintViolated( + nVOKESTATIC, + "Referenced method '" + + nVOKESTATIC.getText4(this.constantPoolGen) + + "' has ACC_STATIC unset."); + } + } catch (ClassNotFoundException classNotFoundException) { + throw new AssertionViolatedException(("Missing class: " + classNotFoundException.toString())); + } + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/statics/Pass3aVerifier.java b/src/main/java/com/allatori/lib/bcel/verifier/statics/Pass3aVerifier.java new file mode 100644 index 0000000..dd1108d --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/statics/Pass3aVerifier.java @@ -0,0 +1,317 @@ +package com.allatori.lib.bcel.verifier.statics; + +import com.allatori.lib.bcel.Repository; +import com.allatori.lib.bcel.classfile.Attribute; +import com.allatori.lib.bcel.classfile.Code; +import com.allatori.lib.bcel.classfile.CodeException; +import com.allatori.lib.bcel.classfile.LineNumber; +import com.allatori.lib.bcel.classfile.LineNumberTable; +import com.allatori.lib.bcel.classfile.LocalVariable; +import com.allatori.lib.bcel.classfile.LocalVariableTable; +import com.allatori.lib.bcel.classfile.Method; +import com.allatori.lib.bcel.generic.ASTORE; +import com.allatori.lib.bcel.generic.ATHROW; +import com.allatori.lib.bcel.generic.BREAKPOINT; +import com.allatori.lib.bcel.generic.ConstantPoolGen; +import com.allatori.lib.bcel.generic.GotoInstruction; +import com.allatori.lib.bcel.generic.IMPDEP1; +import com.allatori.lib.bcel.generic.IMPDEP2; +import com.allatori.lib.bcel.generic.Instruction; +import com.allatori.lib.bcel.generic.InstructionHandle; +import com.allatori.lib.bcel.generic.InstructionList; +import com.allatori.lib.bcel.generic.JsrInstruction; +import com.allatori.lib.bcel.generic.RET; +import com.allatori.lib.bcel.generic.ReturnInstruction; +import com.allatori.lib.bcel.verifier.PassVerifier; +import com.allatori.lib.bcel.verifier.VerificationResult; +import com.allatori.lib.bcel.verifier.Verifier; +import com.allatori.lib.bcel.verifier.exc.AssertionViolatedException; +import com.allatori.lib.bcel.verifier.exc.InvalidMethodException; +import com.allatori.lib.bcel.verifier.exc.LoadingException; +import com.allatori.lib.bcel.verifier.exc.StaticCodeInstructionConstraintException; +import com.allatori.lib.bcel.verifier.exc.StaticCodeInstructionOperandConstraintException; + +public final class Pass3aVerifier extends PassVerifier { + + public int method_no; + + public InstructionList instructionList; + + public Verifier myOwner; + + public Code code; + + public void pass3StaticInstructionChecks() { + if (this.code.getCode().length >= 65536) { + throw new StaticCodeInstructionOperandConstraintException( + ("Code array in code attribute '" + + this.code + + "' too big: must be smaller than 65536 bytes.")); + } + InstructionHandle instructionHandle; + for (InstructionHandle instructionHandle2 = instructionHandle = this.instructionList.getStart(); + instructionHandle2 != null; + instructionHandle2 = instructionHandle = instructionHandle.getInstructionHandle2()) { + Instruction instruction; + if ((instruction = instructionHandle.getInstruction()) instanceof IMPDEP1) { + throw new StaticCodeInstructionOperandConstraintException( + "IMPDEP1 must not be in the code, it is an illegal instruction for _internal_ JVM" + + " use!"); + } + if (instruction instanceof IMPDEP2) { + throw new StaticCodeInstructionOperandConstraintException( + "IMPDEP2 must not be in the code, it is an illegal instruction for _internal_ JVM" + + " use!"); + } + if (instruction instanceof BREAKPOINT) { + throw new StaticCodeInstructionOperandConstraintException( + "BREAKPOINT must not be in the code, it is an illegal instruction for _internal_ JVM" + + " use!"); + } + } + Instruction instruction2; + if (!((instruction2 = this.instructionList.getEnd().getInstruction()) + instanceof ReturnInstruction) + && !(instruction2 instanceof RET) + && !(instruction2 instanceof GotoInstruction) + && !(instruction2 instanceof ATHROW)) { + throw new StaticCodeInstructionOperandConstraintException( + "Execution must not fall off the bottom of the code array. This constraint is enforced" + + " statically as some existing verifiers do - so it may be a false alarm if the last" + + " instruction is not reachable."); + } + } + + @Override + public VerificationResult getVerificationResult() { + Pass3aVerifier pass3aVerifier; + try { + if (!this.myOwner + .createVerificationResult2() + .equals(VerificationResult.VERIFICATION_RESULT2)) { + return VerificationResult.VERIFICATION_RESULT; + } + Method[] methods = Repository.lookupClass(this.myOwner.getClassName()).getMethods(); + if (this.method_no >= methods.length) { + throw new InvalidMethodException("METHOD DOES NOT EXIST!"); + } + Method method = methods[this.method_no]; + this.code = method.getCode(); + if (method.isEnabled15() || method.isEnabled14()) { + return VerificationResult.VERIFICATION_RESULT2; + } + try { + this.instructionList = new InstructionList(method.getCode().getCode()); + } catch (RuntimeException runtimeException) { + return new VerificationResult( + 2, "Bad bytecode in the code array of the Code attribute of method '" + method + "'."); + } + pass3aVerifier = this; + } catch (ClassNotFoundException classNotFoundException) { + throw new AssertionViolatedException(("Missing class: " + classNotFoundException.toString())); + } + pass3aVerifier.instructionList.setPositions(true); + VerificationResult verificationResult = VerificationResult.VERIFICATION_RESULT2; + try { + this.delayedPass2Checks(); + } catch (LoadingException loadingException) { + return new VerificationResult(2, loadingException.getMessage()); + } + this.pass3StaticInstructionChecks(); + this.pass3StaticInstructionOperandsChecks(); + return verificationResult; + } + + public int getMethodNo() { + return this.method_no; + } + + public void pass3StaticInstructionOperandsChecks() { + try { + ConstantPoolGen constantPoolGen = + new ConstantPoolGen( + Repository.lookupClass(this.myOwner.getClassName()).getConstantPool()); + Pass3aVerifier$InstOperandConstraintVisitor pass3aVerifier$InstOperandConstraintVisitor = + new Pass3aVerifier$InstOperandConstraintVisitor(this, constantPoolGen); + for (InstructionHandle start = this.instructionList.getStart(); + start != null; + start = start.getInstructionHandle2()) { + Instruction instruction; + if ((instruction = start.getInstruction()) instanceof JsrInstruction) { + InstructionHandle instructionHandle; + if ((instructionHandle = ((JsrInstruction) instruction).getTarget()) + == this.instructionList.getStart()) { + throw new StaticCodeInstructionConstraintException( + ("Due to JustIce's clear definition of subroutines, no JSR or JSR_W may have a" + + " top-level instruction (such as the very first instruction, which is" + + " targeted by instruction '" + + start + + "' as its target.")); + } + if (!(instructionHandle.getInstruction() instanceof ASTORE)) { + throw new StaticCodeInstructionConstraintException( + ("Due to JustIce's clear definition of subroutines, no JSR or JSR_W may target" + + " anything else than an ASTORE instruction. Instruction '" + + start + + "' targets '" + + instructionHandle + + "'.")); + } + } + start.accept(pass3aVerifier$InstOperandConstraintVisitor); + } + } catch (ClassNotFoundException classNotFoundException) { + throw new AssertionViolatedException(("Missing class: " + classNotFoundException.toString())); + } + } + + public static boolean contains(int[] values, int value) { + int value2; + for (int value3 = value2 = 0; value3 < values.length; value3 = ++value2) { + if (values[value2] == value) { + return true; + } + } + return false; + } + + public Pass3aVerifier(Verifier verifier, int method_no) { + super(); + this.myOwner = verifier; + this.method_no = method_no; + } + + public static Verifier access$000(Pass3aVerifier pass3aVerifier) { + return pass3aVerifier.myOwner; + } + + public void delayedPass2Checks() { + int[] instructionPositions = this.instructionList.getInstructionPositions(); + int value = this.code.getCode().length; + LineNumberTable lineNumberTable; + if ((lineNumberTable = this.code.getLineNumberTable()) != null) { + LineNumber[] lineNumberTable2 = lineNumberTable.getLineNumberTable(); + IntList intList = new IntList(); + int value2; + label87: + for (int value3 = value2 = 0; value3 < lineNumberTable2.length; value3 = ++value2) { + int value4; + for (int value5 = value4 = 0; value5 < instructionPositions.length; value5 = ++value4) { + int start_pc = lineNumberTable2[value2].getStart_pc(); + if (instructionPositions[value4] == start_pc) { + if (intList.contains(start_pc)) { + this.addMessage( + "LineNumberTable attribute '" + + this.code.getLineNumberTable() + + "' refers to the same code offset ('" + + start_pc + + "') more than once which is violating the semantics [but is sometimes" + + " produced by IBM's 'jikes' compiler]."); + } else { + intList.add(start_pc); + } + continue label87; + } + } + throw new LoadingException( + ("Code attribute '" + + this.code + + "' has a LineNumberTable attribute '" + + this.code.getLineNumberTable() + + "' referring to a code offset ('" + + lineNumberTable2[value2].getStart_pc() + + "') that does not exist.")); + } + } + Attribute[] attributes = this.code.getAttributes(); + int value6; + for (int value7 = value6 = 0; value7 < attributes.length; value7 = ++value6) { + LocalVariableTable localVariableTable; + if (attributes[value6] instanceof LocalVariableTable + && (localVariableTable = (LocalVariableTable) attributes[value6]) != null) { + LocalVariable[] localVariableTable2 = localVariableTable.getLocalVariableTable(); + int value8; + for (int value9 = value8 = 0; value9 < localVariableTable2.length; value9 = ++value8) { + int start_pc2 = localVariableTable2[value8].getStart_pc(); + int length2 = localVariableTable2[value8].getLength(); + if (!contains(instructionPositions, start_pc2)) { + throw new LoadingException( + ("Code attribute '" + + this.code + + "' has a LocalVariableTable attribute '" + + this.code.getLocalVariableTable() + + "' referring to a code offset ('" + + start_pc2 + + "') that does not exist.")); + } + if (!contains(instructionPositions, start_pc2 + length2) + && start_pc2 + length2 != value) { + throw new LoadingException( + ("Code attribute '" + + this.code + + "' has a LocalVariableTable attribute '" + + this.code.getLocalVariableTable() + + "' referring to a code offset start_pc+length ('" + + (start_pc2 + length2) + + "') that does not exist.")); + } + } + } + } + CodeException[] exceptionTable = this.code.getExceptionTable(); + int value10; + for (int value11 = value10 = 0; value11 < exceptionTable.length; value11 = ++value10) { + int start_pc3 = exceptionTable[value10].getStart_pc(); + int end_pc = exceptionTable[value10].getEnd_pc(); + int handler_pc = exceptionTable[value10].getHandler_pc(); + if (start_pc3 >= end_pc) { + throw new LoadingException( + ("Code attribute '" + + this.code + + "' has an exception_table entry '" + + exceptionTable[value10] + + "' that has its start_pc ('" + + start_pc3 + + "') not smaller than its end_pc ('" + + end_pc + + "').")); + } + if (!contains(instructionPositions, start_pc3)) { + throw new LoadingException( + ("Code attribute '" + + this.code + + "' has an exception_table entry '" + + exceptionTable[value10] + + "' that has a non-existant bytecode offset as its start_pc ('" + + start_pc3 + + "').")); + } + if (!contains(instructionPositions, end_pc) && end_pc != value) { + throw new LoadingException( + ("Code attribute '" + + this.code + + "' has an exception_table entry '" + + exceptionTable[value10] + + "' that has a non-existant bytecode offset as its end_pc ('" + + start_pc3 + + "') [that is also not equal to code_length ('" + + value + + "')].")); + } + if (!contains(instructionPositions, handler_pc)) { + throw new LoadingException( + ("Code attribute '" + + this.code + + "' has an exception_table entry '" + + exceptionTable[value10] + + "' that has a non-existant bytecode offset as its handler_pc ('" + + handler_pc + + "').")); + } + } + } + + public static int access$100(Pass3aVerifier pass3aVerifier) { + return pass3aVerifier.method_no; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/statics/StringRepresentation.java b/src/main/java/com/allatori/lib/bcel/verifier/statics/StringRepresentation.java new file mode 100644 index 0000000..4bf440b --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/statics/StringRepresentation.java @@ -0,0 +1,215 @@ +package com.allatori.lib.bcel.verifier.statics; + +import com.allatori.lib.bcel.classfile.Code; +import com.allatori.lib.bcel.classfile.CodeException; +import com.allatori.lib.bcel.classfile.ConstantClass; +import com.allatori.lib.bcel.classfile.ConstantDouble; +import com.allatori.lib.bcel.classfile.ConstantFieldref; +import com.allatori.lib.bcel.classfile.ConstantFloat; +import com.allatori.lib.bcel.classfile.ConstantInteger; +import com.allatori.lib.bcel.classfile.ConstantInterfaceMethodref; +import com.allatori.lib.bcel.classfile.ConstantLong; +import com.allatori.lib.bcel.classfile.ConstantMethodref; +import com.allatori.lib.bcel.classfile.ConstantNameAndType; +import com.allatori.lib.bcel.classfile.ConstantPool; +import com.allatori.lib.bcel.classfile.ConstantString; +import com.allatori.lib.bcel.classfile.ConstantUtf8; +import com.allatori.lib.bcel.classfile.ConstantValue; +import com.allatori.lib.bcel.classfile.Deprecated; +import com.allatori.lib.bcel.classfile.EmptyVisitor; +import com.allatori.lib.bcel.classfile.ExceptionTable; +import com.allatori.lib.bcel.classfile.Field; +import com.allatori.lib.bcel.classfile.InnerClass; +import com.allatori.lib.bcel.classfile.InnerClasses; +import com.allatori.lib.bcel.classfile.JavaClass; +import com.allatori.lib.bcel.classfile.LineNumber; +import com.allatori.lib.bcel.classfile.LineNumberTable; +import com.allatori.lib.bcel.classfile.LocalVariable; +import com.allatori.lib.bcel.classfile.LocalVariableTable; +import com.allatori.lib.bcel.classfile.Method; +import com.allatori.lib.bcel.classfile.Node; +import com.allatori.lib.bcel.classfile.Signature; +import com.allatori.lib.bcel.classfile.SourceFile; +import com.allatori.lib.bcel.classfile.StackMap; +import com.allatori.lib.bcel.classfile.Synthetic; +import com.allatori.lib.bcel.classfile.Unknown; +import com.allatori.lib.bcel.classfile.Visitor; + +public class StringRepresentation extends EmptyVisitor implements Visitor { + + public Node n; + + public String tostring; + + @Override + public void visitJavaClass(JavaClass javaClass) { + this.tostring = this.toString(javaClass); + } + + @Override + public void visitCode(Code code) { + this.tostring = ""; + } + + @Override + public void visitLineNumber(LineNumber lineNumber) { + this.tostring = this.toString(lineNumber); + } + + @Override + public void visitConstantValue(ConstantValue constantValue) { + this.tostring = this.toString(constantValue); + } + + @Override + public void visitLocalVariableTable(LocalVariableTable localVariableTable) { + this.tostring = ""; + } + + @Override + public void visitConstantLong(ConstantLong constantLong) { + this.tostring = this.toString(constantLong); + } + + @Override + public void visitField(Field field) { + this.tostring = this.toString(field); + } + + @Override + public void visitSourceFile(SourceFile sourceFile) { + this.tostring = this.toString(sourceFile); + } + + @Override + public void visitConstantFieldref(ConstantFieldref constantFieldref) { + this.tostring = this.toString(constantFieldref); + } + + @Override + public void visitConstantClass(ConstantClass constantClass) { + this.tostring = this.toString(constantClass); + } + + @Override + public void visitConstantPool(ConstantPool constantPool) { + this.tostring = this.toString(constantPool); + } + + @Override + public void visitConstantInteger(ConstantInteger constantInteger) { + this.tostring = this.toString(constantInteger); + } + + @Override + public void visitStackMap(StackMap stackMap) { + this.tostring = this.toString(stackMap); + } + + @Override + public void visitMethod(Method method) { + this.tostring = this.toString(method); + } + + @Override + public void visitInnerClass(InnerClass innerClass) { + this.tostring = this.toString(innerClass); + } + + @Override + public void visitConstantNameAndType(ConstantNameAndType constantNameAndType) { + this.tostring = this.toString(constantNameAndType); + } + + @Override + public void visitConstantMethodref(ConstantMethodref constantMethodref) { + this.tostring = this.toString(constantMethodref); + } + + public String toString(Node node) { + try { + return node.toString(); + } catch (RuntimeException runtimeException) { + String name = node.getClass().getName(); + String text = name.substring(name.lastIndexOf(".") + 1); + return "<<" + text + ">>"; + } + } + + @Override + public void visitLocalVariable(LocalVariable localVariable) { + this.tostring = this.toString(localVariable); + } + + @Override + public void visitConstantFloat(ConstantFloat constantFloat) { + this.tostring = this.toString(constantFloat); + } + + @Override + public void visitConstantUtf8(ConstantUtf8 constantUtf8) { + this.tostring = this.toString(constantUtf8); + } + + @Override + public void visitUnknown(Unknown unknown) { + this.tostring = this.toString(unknown); + } + + @Override + public void visitExceptionTable(ExceptionTable exceptionTable) { + this.tostring = this.toString(exceptionTable); + } + + @Override + public void visitConstantString(ConstantString constantString) { + this.tostring = this.toString(constantString); + } + + @Override + public void visitDeprecated(Deprecated deprecated) { + this.tostring = this.toString(deprecated); + } + + public StringRepresentation(Node node) { + super(); + this.n = node; + node.accept(this); + } + + @Override + public void visitInnerClasses(InnerClasses innerClasses) { + this.tostring = this.toString(innerClasses); + } + + @Override + public void visitCodeException(CodeException codeException) { + this.tostring = this.toString(codeException); + } + + @Override + public void visitConstantDouble(ConstantDouble constantDouble) { + this.tostring = this.toString(constantDouble); + } + + @Override + public void visitLineNumberTable(LineNumberTable lineNumberTable) { + this.tostring = ""; + } + + @Override + public void visitSignature(Signature signature) { + this.tostring = this.toString(signature); + } + + @Override + public void visitConstantInterfaceMethodref( + ConstantInterfaceMethodref constantInterfaceMethodref) { + this.tostring = this.toString(constantInterfaceMethodref); + } + + @Override + public void visitSynthetic(Synthetic synthetic) { + this.tostring = this.toString(synthetic); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/statics/UpperWordType.java b/src/main/java/com/allatori/lib/bcel/verifier/statics/UpperWordType.java new file mode 100644 index 0000000..83e3845 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/statics/UpperWordType.java @@ -0,0 +1,16 @@ +package com.allatori.lib.bcel.verifier.statics; + +import com.allatori.lib.bcel.generic.Type; + +public final class UpperWordType extends Type { + + public static UpperWordType upperWordType = new UpperWordType(); + + public UpperWordType() { + super((byte) 15, "Long_Upper"); + } + + public static UpperWordType getUpperWordType() { + return upperWordType; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/statics/UpperWordType2.java b/src/main/java/com/allatori/lib/bcel/verifier/statics/UpperWordType2.java new file mode 100644 index 0000000..93da10b --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/statics/UpperWordType2.java @@ -0,0 +1,16 @@ +package com.allatori.lib.bcel.verifier.statics; + +import com.allatori.lib.bcel.generic.Type; + +public final class UpperWordType2 extends Type { + + public static UpperWordType2 upperWordType2 = new UpperWordType2(); + + public static UpperWordType2 getUpperWordType2() { + return upperWordType2; + } + + public UpperWordType2() { + super((byte) 15, "Long_Upper"); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/structurals/ControlFlowGraph$InstructionContextImpl.java b/src/main/java/com/allatori/lib/bcel/verifier/structurals/ControlFlowGraph$InstructionContextImpl.java new file mode 100644 index 0000000..07d98d6 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/structurals/ControlFlowGraph$InstructionContextImpl.java @@ -0,0 +1,272 @@ +package com.allatori.lib.bcel.verifier.structurals; + +import com.allatori.lib.bcel.generic.ATHROW; +import com.allatori.lib.bcel.generic.BranchInstruction; +import com.allatori.lib.bcel.generic.GotoInstruction; +import com.allatori.lib.bcel.generic.Instruction; +import com.allatori.lib.bcel.generic.InstructionHandle; +import com.allatori.lib.bcel.generic.JsrInstruction; +import com.allatori.lib.bcel.generic.RET; +import com.allatori.lib.bcel.generic.ReturnInstruction; +import com.allatori.lib.bcel.generic.Select; +import com.allatori.lib.bcel.verifier.exc.AssertionViolatedException; +import com.allatori.lib.bcel.verifier.exc.StructuralCodeConstraintException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +public class ControlFlowGraph$InstructionContextImpl implements InstructionContext { + + public final ControlFlowGraph this$0; + + public ArrayList arrayList; + + public Map entries; + + public int TAG; + + public InstructionHandle instruction; + + public Map entries2; + + public String createText() { + String text = this.toString(); + int value; + for (int value2 = value = this.arrayList.size() - 1; value2 >= 0; value2 = value) { + StringBuilder stringBuilder = + new StringBuilder().append(this.arrayList.get(value)).append("\n"); + String text2 = text; + value--; + text = stringBuilder.append(text2).toString(); + } + return text; + } + + public boolean mergeInFrames(Frame frame) { + Frame frame2; + Frame frame3 = frame2 = (Frame) this.entries2.get(this.lastExecutionJSR()); + OperandStack clone = frame3.getStack().getClone(); + LocalVariables clone2 = frame3.getLocals().getClone(); + try { + frame2.getStack().merge(frame.getStack()); + frame2.getLocals().merge(frame.getLocals()); + } catch (StructuralCodeConstraintException structuralCodeConstraintException) { + this.extendMessageWithFlow(structuralCodeConstraintException); + throw structuralCodeConstraintException; + } + return !clone.equals(frame2.getStack()) || !clone2.equals(frame2.getLocals()); + } + + @Override + public void setTag(int TAG) { + this.TAG = TAG; + } + + public void extendMessageWithFlow( + StructuralCodeConstraintException structuralCodeConstraintException) { + structuralCodeConstraintException.extendMessage( + "", "" + ((String) "Execution flow:\n") + this.createText()); + } + + public InstructionHandle[] _getSuccessors() { + InstructionHandle[] instructionHandles = new InstructionHandle[0]; + InstructionHandle[] instructionHandles2 = new InstructionHandle[1]; + InstructionHandle[] instructionHandles3 = new InstructionHandle[2]; + Instruction instruction; + if (!((instruction = this.getInstruction().getInstruction()) instanceof RET)) { + if (instruction instanceof ReturnInstruction) { + return instructionHandles; + } + if (instruction instanceof ATHROW) { + return instructionHandles; + } + if (instruction instanceof JsrInstruction) { + instructionHandles2[0] = ((JsrInstruction) instruction).getTarget(); + return instructionHandles2; + } + if (instruction instanceof GotoInstruction) { + instructionHandles2[0] = ((GotoInstruction) instruction).getTarget(); + return instructionHandles2; + } + if (instruction instanceof BranchInstruction) { + if (instruction instanceof Select) { + InstructionHandle[] instructionHandles4; + InstructionHandle[] instructionHandles5; + (instructionHandles5 = + new InstructionHandle + [(instructionHandles4 = ((Select) instruction).getTargets()).length + 1]) + [0] = + ((Select) instruction).getTarget(); + System.arraycopy( + instructionHandles4, 0, instructionHandles5, 1, instructionHandles4.length); + return instructionHandles5; + } else { + instructionHandles3[0] = this.getInstruction().getInstructionHandle2(); + instructionHandles3[1] = ((BranchInstruction) instruction).getTarget(); + return instructionHandles3; + } + } else { + instructionHandles2[0] = this.getInstruction().getInstructionHandle2(); + return instructionHandles2; + } + } else { + Subroutine subroutine; + if ((subroutine = + ControlFlowGraph.access$100(this.this$0).subroutineOf(this.getInstruction())) + == null) { + throw new AssertionViolatedException("Asking for successors of a RET in dead code?!"); + } + InstructionHandle[] instructionHandles6; + InstructionHandle[] instructionHandles7 = + new InstructionHandle[(instructionHandles6 = subroutine.getInstructionHandles()).length]; + int value; + for (int value2 = value = 0; value2 < instructionHandles6.length; value2 = value) { + InstructionHandle instructionHandle2 = instructionHandles6[value].getInstructionHandle2(); + int value3 = value; + value++; + instructionHandles7[value3] = instructionHandle2; + } + return instructionHandles7; + } + } + + @Override + public InstructionHandle getInstruction() { + return this.instruction; + } + + @Override + public int getTag() { + return this.TAG; + } + + public ControlFlowGraph$InstructionContextImpl lastExecutionJSR() { + int size2 = this.arrayList.size(); + int value = 0; + int value2; + for (int value3 = value2 = size2 - 1; value3 >= 0; value3 = --value2) { + Instruction instruction; + ControlFlowGraph$InstructionContextImpl controlFlowGraph$InstructionContextImpl; + if ((instruction = + (controlFlowGraph$InstructionContextImpl = + (ControlFlowGraph$InstructionContextImpl) this.arrayList.get(value2)) + .getInstruction() + .getInstruction()) + instanceof RET) { + value++; + } + if (instruction instanceof JsrInstruction) { + if (--value == -1) { + return controlFlowGraph$InstructionContextImpl; + } + } + } + return null; + } + + @Override + public InstructionContext[] getSuccessors() { + return this.this$0.contextsOf(this._getSuccessors()); + } + + @Override + public ExceptionHandler[] getExceptionHandlers() { + return ControlFlowGraph.access$000(this.this$0).getExceptionHandlers(this.getInstruction()); + } + + @Override + public Frame getOutFrame(ArrayList arrayList) { + this.arrayList = arrayList; + ControlFlowGraph$InstructionContextImpl controlFlowGraph$InstructionContextImpl = + this.lastExecutionJSR(); + Frame frame; + if ((frame = (Frame) this.entries.get(controlFlowGraph$InstructionContextImpl)) == null) { + throw new AssertionViolatedException( + ("outFrame not set! This:\n" + + this + + "\nExecutionChain: " + + this.createText() + + "\nOutFrames: '" + + this.entries + + "'.")); + } else { + return frame.getClone(); + } + } + + @Override + public Frame getInFrame() { + ControlFlowGraph$InstructionContextImpl controlFlowGraph$InstructionContextImpl = + this.lastExecutionJSR(); + Frame frame; + if ((frame = (Frame) this.entries2.get(controlFlowGraph$InstructionContextImpl)) == null) { + throw new AssertionViolatedException( + ("inFrame not set! This:\n" + this + "\nInFrames: '" + this.entries2 + "'.")); + } else { + return frame.getClone(); + } + } + + @Override + public boolean execute( + Frame frame, + ArrayList values, + InstConstraintVisitor instConstraintVisitor, + ExecutionVisitor executionVisitor) { + this.arrayList = (ArrayList) values.clone(); + if (this.lastExecutionJSR() == null + && ControlFlowGraph.access$100(this.this$0).subroutineOf(this.getInstruction()) + != ControlFlowGraph.access$100(this.this$0).getTopLevel()) { + throw new AssertionViolatedException( + ("Huh?! Am I '" + this + "' part of a subroutine or not?")); + } + if (this.lastExecutionJSR() != null + && ControlFlowGraph.access$100(this.this$0).subroutineOf(this.getInstruction()) + == ControlFlowGraph.access$100(this.this$0).getTopLevel()) { + throw new AssertionViolatedException( + ("Huh?! Am I '" + this + "' part of a subroutine or not?")); + } + Frame frame2; + Frame frame3; + if ((frame2 = (Frame) this.entries2.get(this.lastExecutionJSR())) == null) { + this.entries2.put(this.lastExecutionJSR(), frame); + frame3 = frame; + } else { + if (frame2.equals(frame)) { + return false; + } + if (!this.mergeInFrames(frame)) { + return false; + } + frame3 = frame2; + } + Frame clone2 = frame3.getClone(); + try { + instConstraintVisitor.setFrame(clone2); + this.getInstruction().accept(instConstraintVisitor); + } catch (StructuralCodeConstraintException structuralCodeConstraintException) { + structuralCodeConstraintException.extendMessage( + "", "\nInstructionHandle: " + this.getInstruction() + "\n"); + structuralCodeConstraintException.extendMessage("", "\nExecution Frame:\n" + clone2); + this.extendMessageWithFlow(structuralCodeConstraintException); + throw structuralCodeConstraintException; + } + executionVisitor.setFrame(clone2); + this.getInstruction().accept(executionVisitor); + this.entries.put(this.lastExecutionJSR(), clone2); + return true; + } + + public ControlFlowGraph$InstructionContextImpl( + ControlFlowGraph controlFlowGraph, InstructionHandle instructionHandle) { + super(); + this.this$0 = controlFlowGraph; + this.arrayList = null; + if (instructionHandle == null) { + throw new AssertionViolatedException("Cannot instantiate InstructionContextImpl from NULL."); + } + this.instruction = instructionHandle; + this.entries2 = new HashMap(); + this.entries = new HashMap(); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/structurals/ControlFlowGraph.java b/src/main/java/com/allatori/lib/bcel/verifier/structurals/ControlFlowGraph.java new file mode 100644 index 0000000..e3506d6 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/structurals/ControlFlowGraph.java @@ -0,0 +1,69 @@ +package com.allatori.lib.bcel.verifier.structurals; + +import com.allatori.lib.bcel.generic.InstructionHandle; +import com.allatori.lib.bcel.generic.MethodGen; +import com.allatori.lib.bcel.verifier.exc.AssertionViolatedException; +import java.util.HashMap; +import java.util.Map; + +public class ControlFlowGraph { + + public final Subroutines subroutines; + + public Map entries; + + public final ExceptionHandlers exceptionhandlers; + + public ControlFlowGraph(MethodGen methodGen) { + super(); + this.entries = new HashMap(); + this.subroutines = new Subroutines(methodGen); + this.exceptionhandlers = new ExceptionHandlers(methodGen); + InstructionHandle[] instructionHandles = methodGen.getInstructionList().getInstructionHandles(); + int value; + for (int value2 = value = 0; value2 < instructionHandles.length; value2 = value) { + this.entries.put( + instructionHandles[value], + new ControlFlowGraph$InstructionContextImpl(this, instructionHandles[value++])); + } + } + + public boolean isDead(InstructionHandle instructionHandle) { + return this.subroutines.subroutineOf(instructionHandle) == null; + } + + public InstructionContext[] getInstructionContexts() { + InstructionContext[] instructionContexts = new InstructionContext[this.entries.values().size()]; + return (InstructionContext[]) this.entries.values().toArray(instructionContexts); + } + + public InstructionContext contextOf(InstructionHandle instructionHandle) { + InstructionContext instructionContext; + if ((instructionContext = (InstructionContext) this.entries.get(instructionHandle)) == null) { + throw new AssertionViolatedException( + "InstructionContext requested for an InstructionHandle that's not known!"); + } else { + return instructionContext; + } + } + + public static Subroutines access$100(ControlFlowGraph controlFlowGraph) { + return controlFlowGraph.subroutines; + } + + public static ExceptionHandlers access$000(ControlFlowGraph controlFlowGraph) { + return controlFlowGraph.exceptionhandlers; + } + + public InstructionContext[] contextsOf(InstructionHandle[] instructionHandles) { + InstructionContext[] instructionContexts = new InstructionContext[instructionHandles.length]; + int value; + for (int value2 = value = 0; value2 < instructionHandles.length; value2 = value) { + InstructionContext instructionContext = this.contextOf(instructionHandles[value]); + int value3 = value; + value++; + instructionContexts[value3] = instructionContext; + } + return instructionContexts; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/structurals/ExceptionHandler.java b/src/main/java/com/allatori/lib/bcel/verifier/structurals/ExceptionHandler.java new file mode 100644 index 0000000..5e33274 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/structurals/ExceptionHandler.java @@ -0,0 +1,25 @@ +package com.allatori.lib.bcel.verifier.structurals; + +import com.allatori.lib.bcel.generic.InstructionHandle; +import com.allatori.lib.bcel.generic.ObjectType; + +public class ExceptionHandler { + + public InstructionHandle handlerpc; + + public ObjectType catchtype; + + public InstructionHandle getHandlerStart() { + return this.handlerpc; + } + + public ObjectType getExceptionType() { + return this.catchtype; + } + + public ExceptionHandler(ObjectType objectType, InstructionHandle instructionHandle) { + super(); + this.catchtype = objectType; + this.handlerpc = instructionHandle; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/structurals/ExceptionHandlers.java b/src/main/java/com/allatori/lib/bcel/verifier/structurals/ExceptionHandlers.java new file mode 100644 index 0000000..0a3c56b --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/structurals/ExceptionHandlers.java @@ -0,0 +1,50 @@ +package com.allatori.lib.bcel.verifier.structurals; + +import com.allatori.lib.bcel.generic.CodeExceptionGen; +import com.allatori.lib.bcel.generic.InstructionHandle; +import com.allatori.lib.bcel.generic.MethodGen; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +public class ExceptionHandlers { + + public Map exceptionhandlers; + + public ExceptionHandlers(MethodGen methodGen) { + super(); + this.exceptionhandlers = new HashMap(); + CodeExceptionGen[] exceptionHandlers = methodGen.getExceptionHandlers(); + int value; + for (int value2 = value = 0; value2 < exceptionHandlers.length; value2 = ++value) { + ExceptionHandler exceptionHandler = + new ExceptionHandler( + exceptionHandlers[value].getCatchType(), + exceptionHandlers[value].getInstructionHandle3()); + InstructionHandle instructionHandle; + for (InstructionHandle instructionHandle2 = + instructionHandle = exceptionHandlers[value].getInstructionHandle2(); + instructionHandle2 + != exceptionHandlers[value].getInstructionHandle().getInstructionHandle2(); + instructionHandle2 = instructionHandle) { + Set values; + if ((values = (Set) this.exceptionhandlers.get(instructionHandle)) == null) { + values = new HashSet(); + this.exceptionhandlers.put(instructionHandle, values); + } + values.add(exceptionHandler); + instructionHandle = instructionHandle.getInstructionHandle2(); + } + } + } + + public ExceptionHandler[] getExceptionHandlers(InstructionHandle instructionHandle) { + Set values; + if ((values = (Set) this.exceptionhandlers.get(instructionHandle)) == null) { + return new ExceptionHandler[0]; + } + ExceptionHandler[] exceptionHandlers = new ExceptionHandler[values.size()]; + return (ExceptionHandler[]) values.toArray(exceptionHandlers); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/structurals/ExecutionVisitor.java b/src/main/java/com/allatori/lib/bcel/verifier/structurals/ExecutionVisitor.java new file mode 100644 index 0000000..5c345fa --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/structurals/ExecutionVisitor.java @@ -0,0 +1,1278 @@ +package com.allatori.lib.bcel.verifier.structurals; + +import com.allatori.lib.bcel.classfile.Constant; +import com.allatori.lib.bcel.classfile.ConstantDouble; +import com.allatori.lib.bcel.classfile.ConstantFloat; +import com.allatori.lib.bcel.classfile.ConstantInteger; +import com.allatori.lib.bcel.classfile.ConstantLong; +import com.allatori.lib.bcel.classfile.ConstantString; +import com.allatori.lib.bcel.generic.AALOAD; +import com.allatori.lib.bcel.generic.AASTORE; +import com.allatori.lib.bcel.generic.ACONST_NULL; +import com.allatori.lib.bcel.generic.ALOAD; +import com.allatori.lib.bcel.generic.ANEWARRAY; +import com.allatori.lib.bcel.generic.ARETURN; +import com.allatori.lib.bcel.generic.ARRAYLENGTH; +import com.allatori.lib.bcel.generic.ASTORE; +import com.allatori.lib.bcel.generic.ATHROW; +import com.allatori.lib.bcel.generic.ArrayType; +import com.allatori.lib.bcel.generic.BALOAD; +import com.allatori.lib.bcel.generic.BASTORE; +import com.allatori.lib.bcel.generic.BIPUSH; +import com.allatori.lib.bcel.generic.CALOAD; +import com.allatori.lib.bcel.generic.CASTORE; +import com.allatori.lib.bcel.generic.CHECKCAST; +import com.allatori.lib.bcel.generic.ConstantPoolGen; +import com.allatori.lib.bcel.generic.D2F; +import com.allatori.lib.bcel.generic.D2I; +import com.allatori.lib.bcel.generic.D2L; +import com.allatori.lib.bcel.generic.DADD; +import com.allatori.lib.bcel.generic.DALOAD; +import com.allatori.lib.bcel.generic.DASTORE; +import com.allatori.lib.bcel.generic.DCMPG; +import com.allatori.lib.bcel.generic.DCMPL; +import com.allatori.lib.bcel.generic.DCONST; +import com.allatori.lib.bcel.generic.DDIV; +import com.allatori.lib.bcel.generic.DLOAD; +import com.allatori.lib.bcel.generic.DMUL; +import com.allatori.lib.bcel.generic.DNEG; +import com.allatori.lib.bcel.generic.DREM; +import com.allatori.lib.bcel.generic.DRETURN; +import com.allatori.lib.bcel.generic.DSTORE; +import com.allatori.lib.bcel.generic.DSUB; +import com.allatori.lib.bcel.generic.DUP; +import com.allatori.lib.bcel.generic.DUP2; +import com.allatori.lib.bcel.generic.DUP2_X1; +import com.allatori.lib.bcel.generic.DUP2_X2; +import com.allatori.lib.bcel.generic.DUP_X1; +import com.allatori.lib.bcel.generic.DUP_X2; +import com.allatori.lib.bcel.generic.EmptyVisitor; +import com.allatori.lib.bcel.generic.F2D; +import com.allatori.lib.bcel.generic.F2I; +import com.allatori.lib.bcel.generic.F2L; +import com.allatori.lib.bcel.generic.FADD; +import com.allatori.lib.bcel.generic.FALOAD; +import com.allatori.lib.bcel.generic.FASTORE; +import com.allatori.lib.bcel.generic.FCMPG; +import com.allatori.lib.bcel.generic.FCMPL; +import com.allatori.lib.bcel.generic.FCONST; +import com.allatori.lib.bcel.generic.FDIV; +import com.allatori.lib.bcel.generic.FLOAD; +import com.allatori.lib.bcel.generic.FMUL; +import com.allatori.lib.bcel.generic.FNEG; +import com.allatori.lib.bcel.generic.FREM; +import com.allatori.lib.bcel.generic.FRETURN; +import com.allatori.lib.bcel.generic.FSTORE; +import com.allatori.lib.bcel.generic.FSUB; +import com.allatori.lib.bcel.generic.GETFIELD; +import com.allatori.lib.bcel.generic.GETSTATIC; +import com.allatori.lib.bcel.generic.GOTO; +import com.allatori.lib.bcel.generic.GOTO_W; +import com.allatori.lib.bcel.generic.I2B; +import com.allatori.lib.bcel.generic.I2C; +import com.allatori.lib.bcel.generic.I2D; +import com.allatori.lib.bcel.generic.I2F; +import com.allatori.lib.bcel.generic.I2L; +import com.allatori.lib.bcel.generic.I2S; +import com.allatori.lib.bcel.generic.IADD; +import com.allatori.lib.bcel.generic.IALOAD; +import com.allatori.lib.bcel.generic.IAND; +import com.allatori.lib.bcel.generic.IASTORE; +import com.allatori.lib.bcel.generic.ICONST; +import com.allatori.lib.bcel.generic.IDIV; +import com.allatori.lib.bcel.generic.IFEQ; +import com.allatori.lib.bcel.generic.IFGE; +import com.allatori.lib.bcel.generic.IFGT; +import com.allatori.lib.bcel.generic.IFLE; +import com.allatori.lib.bcel.generic.IFLT; +import com.allatori.lib.bcel.generic.IFNE; +import com.allatori.lib.bcel.generic.IFNONNULL; +import com.allatori.lib.bcel.generic.IFNULL; +import com.allatori.lib.bcel.generic.IF_ACMPEQ; +import com.allatori.lib.bcel.generic.IF_ACMPNE; +import com.allatori.lib.bcel.generic.IF_ICMPEQ; +import com.allatori.lib.bcel.generic.IF_ICMPGE; +import com.allatori.lib.bcel.generic.IF_ICMPGT; +import com.allatori.lib.bcel.generic.IF_ICMPLE; +import com.allatori.lib.bcel.generic.IF_ICMPLT; +import com.allatori.lib.bcel.generic.IF_ICMPNE; +import com.allatori.lib.bcel.generic.IINC; +import com.allatori.lib.bcel.generic.ILOAD; +import com.allatori.lib.bcel.generic.IMUL; +import com.allatori.lib.bcel.generic.INEG; +import com.allatori.lib.bcel.generic.INSTANCEOF; +import com.allatori.lib.bcel.generic.INVOKEINTERFACE; +import com.allatori.lib.bcel.generic.INVOKESPECIAL; +import com.allatori.lib.bcel.generic.INVOKESTATIC; +import com.allatori.lib.bcel.generic.INVOKEVIRTUAL; +import com.allatori.lib.bcel.generic.IOR; +import com.allatori.lib.bcel.generic.IREM; +import com.allatori.lib.bcel.generic.IRETURN; +import com.allatori.lib.bcel.generic.ISHL; +import com.allatori.lib.bcel.generic.ISHR; +import com.allatori.lib.bcel.generic.ISTORE; +import com.allatori.lib.bcel.generic.ISUB; +import com.allatori.lib.bcel.generic.IUSHR; +import com.allatori.lib.bcel.generic.IXOR; +import com.allatori.lib.bcel.generic.JSR; +import com.allatori.lib.bcel.generic.JSR_W; +import com.allatori.lib.bcel.generic.L2D; +import com.allatori.lib.bcel.generic.L2F; +import com.allatori.lib.bcel.generic.L2I; +import com.allatori.lib.bcel.generic.LADD; +import com.allatori.lib.bcel.generic.LALOAD; +import com.allatori.lib.bcel.generic.LAND; +import com.allatori.lib.bcel.generic.LASTORE; +import com.allatori.lib.bcel.generic.LCMP; +import com.allatori.lib.bcel.generic.LCONST; +import com.allatori.lib.bcel.generic.LDC; +import com.allatori.lib.bcel.generic.LDC2_W; +import com.allatori.lib.bcel.generic.LDC_W; +import com.allatori.lib.bcel.generic.LDIV; +import com.allatori.lib.bcel.generic.LLOAD; +import com.allatori.lib.bcel.generic.LMUL; +import com.allatori.lib.bcel.generic.LNEG; +import com.allatori.lib.bcel.generic.LOOKUPSWITCH; +import com.allatori.lib.bcel.generic.LOR; +import com.allatori.lib.bcel.generic.LREM; +import com.allatori.lib.bcel.generic.LRETURN; +import com.allatori.lib.bcel.generic.LSHL; +import com.allatori.lib.bcel.generic.LSHR; +import com.allatori.lib.bcel.generic.LSTORE; +import com.allatori.lib.bcel.generic.LSUB; +import com.allatori.lib.bcel.generic.LUSHR; +import com.allatori.lib.bcel.generic.LXOR; +import com.allatori.lib.bcel.generic.MONITORENTER; +import com.allatori.lib.bcel.generic.MONITOREXIT; +import com.allatori.lib.bcel.generic.MULTIANEWARRAY; +import com.allatori.lib.bcel.generic.NEW; +import com.allatori.lib.bcel.generic.NEWARRAY; +import com.allatori.lib.bcel.generic.NOP; +import com.allatori.lib.bcel.generic.ObjectType; +import com.allatori.lib.bcel.generic.POP; +import com.allatori.lib.bcel.generic.POP2; +import com.allatori.lib.bcel.generic.PUTFIELD; +import com.allatori.lib.bcel.generic.PUTSTATIC; +import com.allatori.lib.bcel.generic.RET; +import com.allatori.lib.bcel.generic.RETURN; +import com.allatori.lib.bcel.generic.ReturnaddressType; +import com.allatori.lib.bcel.generic.SALOAD; +import com.allatori.lib.bcel.generic.SASTORE; +import com.allatori.lib.bcel.generic.SIPUSH; +import com.allatori.lib.bcel.generic.SWAP; +import com.allatori.lib.bcel.generic.TABLESWITCH; +import com.allatori.lib.bcel.generic.Type; +import com.allatori.lib.bcel.generic.Visitor; + +public class ExecutionVisitor extends EmptyVisitor implements Visitor { + + public Frame frame = null; + + public ConstantPoolGen cpg = null; + + @Override + public void visitLSTORE(LSTORE lSTORE) { + this.locals().set(lSTORE.getIndex(), this.stack().pop()); + this.locals().set(lSTORE.getIndex() + 1, Type.UNKNOWN); + } + + @Override + public void visitLASTORE(LASTORE lASTORE) { + this.stack().pop(); + this.stack().pop(); + this.stack().pop(); + } + + @Override + public void visitIF_ICMPGE(IF_ICMPGE f_ICMPGE) { + this.stack().pop(); + this.stack().pop(); + } + + @Override + public void visitBASTORE(BASTORE bASTORE) { + this.stack().pop(); + this.stack().pop(); + this.stack().pop(); + } + + @Override + public void visitANEWARRAY(ANEWARRAY aNEWARRAY) { + this.stack().pop(); + this.stack().push(new ArrayType(aNEWARRAY.getType(this.cpg), 1)); + } + + @Override + public void visitINVOKEINTERFACE(INVOKEINTERFACE nVOKEINTERFACE) { + this.stack().pop(); + int value = 0; + for (int value2 = value; + value2 < nVOKEINTERFACE.getArgumentTypes(this.cpg).length; + value2 = value) { + value++; + this.stack().pop(); + } + if (nVOKEINTERFACE.getType2(this.cpg) != Type.VOID) { + Type type; + if ((type = nVOKEINTERFACE.getType2(this.cpg)).equals(Type.BOOLEAN) + || type.equals(Type.CHAR) + || type.equals(Type.BYTE) + || type.equals(Type.SHORT)) { + type = Type.INT; + } + this.stack().push(type); + } + } + + @Override + public void visitNEWARRAY(NEWARRAY nEWARRAY) { + this.stack().pop(); + this.stack().push(nEWARRAY.getType()); + } + + @Override + public void visitIRETURN(IRETURN rETURN) { + this.stack().pop(); + } + + @Override + public void visitFSTORE(FSTORE fSTORE) { + this.locals().set(fSTORE.getIndex(), this.stack().pop()); + } + + @Override + public void visitI2B(I2B i2B) { + this.stack().pop(); + this.stack().push(Type.INT); + } + + @Override + public void visitFCMPL(FCMPL fCMPL) { + this.stack().pop(); + this.stack().pop(); + this.stack().push(Type.INT); + } + + @Override + public void visitINSTANCEOF(INSTANCEOF nSTANCEOF) { + this.stack().pop(); + this.stack().push(Type.INT); + } + + @Override + public void visitIFLE(IFLE fLE) { + this.stack().pop(); + } + + @Override + public void visitMONITORENTER(MONITORENTER mONITORENTER) { + this.stack().pop(); + } + + @Override + public void visitI2C(I2C i2C) { + this.stack().pop(); + this.stack().push(Type.INT); + } + + @Override + public void visitIF_ICMPNE(IF_ICMPNE f_ICMPNE) { + this.stack().pop(); + this.stack().pop(); + } + + @Override + public void visitISTORE(ISTORE sTORE) { + this.locals().set(sTORE.getIndex(), this.stack().pop()); + } + + @Override + public void visitIDIV(IDIV dIV) { + this.stack().pop(); + this.stack().pop(); + this.stack().push(Type.INT); + } + + @Override + public void visitI2F(I2F i2F) { + this.stack().pop(); + this.stack().push(Type.FLOAT); + } + + @Override + public void visitLADD(LADD lADD) { + this.stack().pop(); + this.stack().pop(); + this.stack().push(Type.LONG); + } + + @Override + public void visitLALOAD(LALOAD lALOAD) { + this.stack().pop(); + this.stack().pop(); + this.stack().push(Type.LONG); + } + + @Override + public void visitDLOAD(DLOAD dLOAD) { + this.stack().push(Type.DOUBLE); + } + + @Override + public void visitIMUL(IMUL mUL) { + this.stack().pop(); + this.stack().pop(); + this.stack().push(Type.INT); + } + + @Override + public void visitFDIV(FDIV fDIV) { + this.stack().pop(); + this.stack().pop(); + this.stack().push(Type.FLOAT); + } + + @Override + public void visitBIPUSH(BIPUSH bIPUSH) { + this.stack().push(Type.INT); + } + + @Override + public void visitSALOAD(SALOAD sALOAD) { + this.stack().pop(); + this.stack().pop(); + this.stack().push(Type.INT); + } + + @Override + public void visitLUSHR(LUSHR lUSHR) { + this.stack().pop(); + this.stack().pop(); + this.stack().push(Type.LONG); + } + + @Override + public void visitDSUB(DSUB dSUB) { + this.stack().pop(); + this.stack().pop(); + this.stack().push(Type.DOUBLE); + } + + @Override + public void visitL2I(L2I l2I) { + this.stack().pop(); + this.stack().push(Type.INT); + } + + @Override + public void visitPOP(POP pOP) { + this.stack().pop(); + } + + @Override + public void visitSWAP(SWAP sWAP) { + Type type = this.stack().pop(); + Type type2 = this.stack().pop(); + this.stack().push(type); + this.stack().push(type2); + } + + @Override + public void visitBALOAD(BALOAD bALOAD) { + this.stack().pop(); + this.stack().pop(); + this.stack().push(Type.INT); + } + + @Override + public void visitDREM(DREM dREM) { + this.stack().pop(); + this.stack().pop(); + this.stack().push(Type.DOUBLE); + } + + @Override + public void visitLMUL(LMUL lMUL) { + this.stack().pop(); + this.stack().pop(); + this.stack().push(Type.LONG); + } + + @Override + public void visitJSR_W(JSR_W jSR_W) { + this.stack().push(new ReturnaddressType(jSR_W.physicalSuccessor())); + } + + @Override + public void visitLDC2_W(LDC2_W lDC2_W) { + Constant constant; + if ((constant = this.cpg.getConstant(lDC2_W.getIndex())) instanceof ConstantLong) { + this.stack().push(Type.LONG); + } + if (constant instanceof ConstantDouble) { + this.stack().push(Type.DOUBLE); + } + } + + @Override + public void visitAASTORE(AASTORE aASTORE) { + this.stack().pop(); + this.stack().pop(); + this.stack().pop(); + } + + public void setConstantPoolGen(ConstantPoolGen constantPoolGen) { + this.cpg = constantPoolGen; + } + + public void visitLDC_W(LDC_W lDC_W) { + Constant constant; + if ((constant = this.cpg.getConstant(lDC_W.getIndex())) instanceof ConstantInteger) { + this.stack().push(Type.INT); + } + if (constant instanceof ConstantFloat) { + this.stack().push(Type.FLOAT); + } + if (constant instanceof ConstantString) { + this.stack().push(Type.STRING); + } + } + + @Override + public void visitRETURN(RETURN rETURN) {} + + @Override + public void visitI2D(I2D i2D) { + this.stack().pop(); + this.stack().push(Type.DOUBLE); + } + + @Override + public void visitIAND(IAND aND) { + this.stack().pop(); + this.stack().pop(); + this.stack().push(Type.INT); + } + + @Override + public void visitGOTO(GOTO gOTO) {} + + @Override + public void visitLSHL(LSHL lSHL) { + this.stack().pop(); + this.stack().pop(); + this.stack().push(Type.LONG); + } + + @Override + public void visitIASTORE(IASTORE aSTORE) { + this.stack().pop(); + this.stack().pop(); + this.stack().pop(); + } + + @Override + public void visitIFGT(IFGT fGT) { + this.stack().pop(); + } + + @Override + public void visitISUB(ISUB sUB) { + this.stack().pop(); + this.stack().pop(); + this.stack().push(Type.INT); + } + + @Override + public void visitIOR(IOR oR) { + this.stack().pop(); + this.stack().pop(); + this.stack().push(Type.INT); + } + + @Override + public void visitFMUL(FMUL fMUL) { + this.stack().pop(); + this.stack().pop(); + this.stack().push(Type.FLOAT); + } + + @Override + public void visitRET(RET rET) {} + + @Override + public void visitDCONST(DCONST dCONST) { + this.stack().push(Type.DOUBLE); + } + + @Override + public void visitLRETURN(LRETURN lRETURN) { + this.stack().pop(); + } + + @Override + public void visitIF_ICMPEQ(IF_ICMPEQ f_ICMPEQ) { + this.stack().pop(); + this.stack().pop(); + } + + @Override + public void visitINVOKESTATIC(INVOKESTATIC nVOKESTATIC) { + int value; + for (int value2 = value = 0; + value2 < nVOKESTATIC.getArgumentTypes(this.cpg).length; + value2 = value) { + value++; + this.stack().pop(); + } + if (nVOKESTATIC.getType2(this.cpg) != Type.VOID) { + Type type; + if ((type = nVOKESTATIC.getType2(this.cpg)).equals(Type.BOOLEAN) + || type.equals(Type.CHAR) + || type.equals(Type.BYTE) + || type.equals(Type.SHORT)) { + type = Type.INT; + } + this.stack().push(type); + } + } + + @Override + public void visitFNEG(FNEG fNEG) { + this.stack().pop(); + this.stack().push(Type.FLOAT); + } + + @Override + public void visitFADD(FADD fADD) { + this.stack().pop(); + this.stack().pop(); + this.stack().push(Type.FLOAT); + } + + @Override + public void visitIADD(IADD aDD) { + this.stack().pop(); + this.stack().pop(); + this.stack().push(Type.INT); + } + + @Override + public void visitDUP_X2(DUP_X2 dUP_X2) { + Type type = this.stack().pop(); + Type type2; + if ((type2 = this.stack().pop()).getSize() == 2) { + this.stack().push(type); + this.stack().push(type2); + this.stack().push(type); + } else { + Type type3 = this.stack().pop(); + this.stack().push(type); + this.stack().push(type3); + this.stack().push(type2); + this.stack().push(type); + } + } + + @Override + public void visitLNEG(LNEG lNEG) { + this.stack().pop(); + this.stack().push(Type.LONG); + } + + @Override + public void visitDUP2(DUP2 dUP2) { + Type type; + if ((type = this.stack().pop()).getSize() == 2) { + this.stack().push(type); + this.stack().push(type); + } else { + Type type2 = this.stack().pop(); + this.stack().push(type2); + this.stack().push(type); + this.stack().push(type2); + this.stack().push(type); + } + } + + @Override + public void visitI2L(I2L i2L) { + this.stack().pop(); + this.stack().push(Type.LONG); + } + + @Override + public void visitIALOAD(IALOAD aLOAD) { + this.stack().pop(); + this.stack().pop(); + this.stack().push(Type.INT); + } + + @Override + public void visitNOP(NOP nOP) {} + + @Override + public void visitLOR(LOR lOR) { + this.stack().pop(); + this.stack().pop(); + this.stack().push(Type.LONG); + } + + @Override + public void visitIF_ACMPNE(IF_ACMPNE f_ACMPNE) { + this.stack().pop(); + this.stack().pop(); + } + + @Override + public void visitICONST(ICONST cONST) { + this.stack().push(Type.INT); + } + + @Override + public void visitGOTO_W(GOTO_W gOTO_W) {} + + @Override + public void visitAALOAD(AALOAD aALOAD) { + this.stack().pop(); + Type type = this.stack().pop(); + if (type == Type.NULL) { + this.stack().push(Type.NULL); + } else { + ArrayType arrayType = (ArrayType) type; + this.stack().push(arrayType.getElementType()); + } + } + + @Override + public void visitSIPUSH(SIPUSH sIPUSH) { + this.stack().push(Type.INT); + } + + @Override + public void visitACONST_NULL(ACONST_NULL aCONST_NULL) { + this.stack().push(Type.NULL); + } + + @Override + public void visitLLOAD(LLOAD lLOAD) { + this.stack().push(this.locals().get(lLOAD.getIndex())); + } + + @Override + public void visitDMUL(DMUL dMUL) { + this.stack().pop(); + this.stack().pop(); + this.stack().push(Type.DOUBLE); + } + + @Override + public void visitIFNONNULL(IFNONNULL fNONNULL) { + this.stack().pop(); + } + + @Override + public void visitFALOAD(FALOAD fALOAD) { + this.stack().pop(); + this.stack().pop(); + this.stack().push(Type.FLOAT); + } + + @Override + public void visitDUP(DUP dUP) { + Type type = this.stack().pop(); + this.stack().push(type); + this.stack().push(type); + } + + @Override + public void visitIUSHR(IUSHR uSHR) { + this.stack().pop(); + this.stack().pop(); + this.stack().push(Type.INT); + } + + @Override + public void visitDRETURN(DRETURN dRETURN) { + this.stack().pop(); + } + + @Override + public void visitF2I(F2I f2I) { + this.stack().pop(); + this.stack().push(Type.INT); + } + + @Override + public void visitDALOAD(DALOAD dALOAD) { + this.stack().pop(); + this.stack().pop(); + this.stack().push(Type.DOUBLE); + } + + @Override + public void visitLAND(LAND lAND) { + this.stack().pop(); + this.stack().pop(); + this.stack().push(Type.LONG); + } + + @Override + public void visitIF_ICMPGT(IF_ICMPGT f_ICMPGT) { + this.stack().pop(); + this.stack().pop(); + } + + @Override + public void visitL2F(L2F l2F) { + this.stack().pop(); + this.stack().push(Type.FLOAT); + } + + @Override + public void visitISHL(ISHL sHL) { + this.stack().pop(); + this.stack().pop(); + this.stack().push(Type.INT); + } + + public void setFrame(Frame frame2) { + this.frame = frame2; + } + + @Override + public void visitDUP2_X1(DUP2_X1 dUP2_X1) { + Type type; + if ((type = this.stack().pop()).getSize() == 2) { + Type type2 = this.stack().pop(); + this.stack().push(type); + this.stack().push(type2); + this.stack().push(type); + } else { + Type type3 = this.stack().pop(); + Type type4 = this.stack().pop(); + this.stack().push(type3); + this.stack().push(type); + this.stack().push(type4); + this.stack().push(type3); + this.stack().push(type); + } + } + + @Override + public void visitIF_ICMPLT(IF_ICMPLT f_ICMPLT) { + this.stack().pop(); + this.stack().pop(); + } + + @Override + public void visitALOAD(ALOAD aLOAD) { + this.stack().push(this.locals().get(aLOAD.getIndex())); + } + + @Override + public void visitLREM(LREM lREM) { + this.stack().pop(); + this.stack().pop(); + this.stack().push(Type.LONG); + } + + @Override + public void visitMONITOREXIT(MONITOREXIT mONITOREXIT) { + this.stack().pop(); + } + + @Override + public void visitDCMPG(DCMPG dCMPG) { + this.stack().pop(); + this.stack().pop(); + this.stack().push(Type.INT); + } + + public OperandStack stack() { + return this.frame.getStack(); + } + + @Override + public void visitLOOKUPSWITCH(LOOKUPSWITCH lOOKUPSWITCH) { + this.stack().pop(); + } + + @Override + public void visitCALOAD(CALOAD cALOAD) { + this.stack().pop(); + this.stack().pop(); + this.stack().push(Type.INT); + } + + @Override + public void visitFLOAD(FLOAD fLOAD) { + this.stack().push(Type.FLOAT); + } + + @Override + public void visitFRETURN(FRETURN fRETURN) { + this.stack().pop(); + } + + @Override + public void visitIF_ICMPLE(IF_ICMPLE f_ICMPLE) { + this.stack().pop(); + this.stack().pop(); + } + + @Override + public void visitDCMPL(DCMPL dCMPL) { + this.stack().pop(); + this.stack().pop(); + this.stack().push(Type.INT); + } + + @Override + public void visitD2L(D2L d2L) { + this.stack().pop(); + this.stack().push(Type.LONG); + } + + @Override + public void visitDSTORE(DSTORE dSTORE) { + this.locals().set(dSTORE.getIndex(), this.stack().pop()); + this.locals().set(dSTORE.getIndex() + 1, Type.UNKNOWN); + } + + @Override + public void visitL2D(L2D l2D) { + this.stack().pop(); + this.stack().push(Type.DOUBLE); + } + + @Override + public void visitINVOKEVIRTUAL(INVOKEVIRTUAL nVOKEVIRTUAL) { + this.stack().pop(); + int value = 0; + for (int value2 = value; + value2 < nVOKEVIRTUAL.getArgumentTypes(this.cpg).length; + value2 = value) { + value++; + this.stack().pop(); + } + if (nVOKEVIRTUAL.getType2(this.cpg) != Type.VOID) { + Type type; + if ((type = nVOKEVIRTUAL.getType2(this.cpg)).equals(Type.BOOLEAN) + || type.equals(Type.CHAR) + || type.equals(Type.BYTE) + || type.equals(Type.SHORT)) { + type = Type.INT; + } + this.stack().push(type); + } + } + + @Override + public void visitIFLT(IFLT fLT) { + this.stack().pop(); + } + + @Override + public void visitIINC(IINC iNC) {} + + @Override + public void visitDUP2_X2(DUP2_X2 dUP2_X2) { + Type type; + if ((type = this.stack().pop()).getSize() == 2) { + Type type2; + if ((type2 = this.stack().pop()).getSize() == 2) { + this.stack().push(type); + this.stack().push(type2); + this.stack().push(type); + } else { + Type type3 = this.stack().pop(); + this.stack().push(type); + this.stack().push(type3); + this.stack().push(type2); + this.stack().push(type); + } + } else { + Type type4 = this.stack().pop(); + Type type5; + if ((type5 = this.stack().pop()).getSize() == 2) { + this.stack().push(type4); + this.stack().push(type); + this.stack().push(type5); + this.stack().push(type4); + this.stack().push(type); + } else { + Type type6 = this.stack().pop(); + this.stack().push(type4); + this.stack().push(type); + this.stack().push(type6); + this.stack().push(type5); + this.stack().push(type4); + this.stack().push(type); + } + } + } + + @Override + public void visitDUP_X1(DUP_X1 dUP_X1) { + Type type = this.stack().pop(); + Type type2 = this.stack().pop(); + this.stack().push(type); + this.stack().push(type2); + this.stack().push(type); + } + + @Override + public void visitFCONST(FCONST fCONST) { + this.stack().push(Type.FLOAT); + } + + @Override + public void visitMULTIANEWARRAY(MULTIANEWARRAY mULTIANEWARRAY) { + int value; + for (int value2 = value = 0; value2 < mULTIANEWARRAY.getDimensions(); value2 = value) { + value++; + this.stack().pop(); + } + this.stack().push(mULTIANEWARRAY.getType(this.cpg)); + } + + @Override + public void visitDNEG(DNEG dNEG) { + this.stack().pop(); + this.stack().push(Type.DOUBLE); + } + + @Override + public void visitPUTSTATIC(PUTSTATIC pUTSTATIC) { + this.stack().pop(); + } + + @Override + public void visitIREM(IREM rEM) { + this.stack().pop(); + this.stack().pop(); + this.stack().push(Type.INT); + } + + @Override + public void visitDASTORE(DASTORE dASTORE) { + this.stack().pop(); + this.stack().pop(); + this.stack().pop(); + } + + @Override + public void visitLDC(LDC lDC) { + Constant constant; + if ((constant = this.cpg.getConstant(lDC.getIndex())) instanceof ConstantInteger) { + this.stack().push(Type.INT); + } + if (constant instanceof ConstantFloat) { + this.stack().push(Type.FLOAT); + } + if (constant instanceof ConstantString) { + this.stack().push(Type.STRING); + } + } + + @Override + public void visitF2D(F2D f2D) { + this.stack().pop(); + this.stack().push(Type.DOUBLE); + } + + @Override + public void visitFSUB(FSUB fSUB) { + this.stack().pop(); + this.stack().pop(); + this.stack().push(Type.FLOAT); + } + + @Override + public void visitI2S(I2S i2S) { + this.stack().pop(); + this.stack().push(Type.INT); + } + + @Override + public void visitFCMPG(FCMPG fCMPG) { + this.stack().pop(); + this.stack().pop(); + this.stack().push(Type.INT); + } + + @Override + public void visitLDIV(LDIV lDIV) { + this.stack().pop(); + this.stack().pop(); + this.stack().push(Type.LONG); + } + + @Override + public void visitDADD(DADD dADD) { + this.stack().pop(); + this.stack().pop(); + this.stack().push(Type.DOUBLE); + } + + @Override + public void visitD2I(D2I d2I) { + this.stack().pop(); + this.stack().push(Type.INT); + } + + @Override + public void visitJSR(JSR jSR) { + this.stack().push(new ReturnaddressType(jSR.physicalSuccessor())); + } + + @Override + public void visitARRAYLENGTH(ARRAYLENGTH aRRAYLENGTH) { + this.stack().pop(); + this.stack().push(Type.INT); + } + + @Override + public void visitARETURN(ARETURN aRETURN) { + this.stack().pop(); + } + + @Override + public void visitIFNULL(IFNULL fNULL) { + this.stack().pop(); + } + + @Override + public void visitGETFIELD(GETFIELD gETFIELD) { + this.stack().pop(); + Type type2 = gETFIELD.getType2(this.cpg); + if (type2.equals(Type.BOOLEAN) + || type2.equals(Type.CHAR) + || type2.equals(Type.BYTE) + || type2.equals(Type.SHORT)) { + type2 = Type.INT; + } + this.stack().push(type2); + } + + @Override + public void visitGETSTATIC(GETSTATIC gETSTATIC) { + Type type; + if ((type = gETSTATIC.getType2(this.cpg)).equals(Type.BOOLEAN) + || type.equals(Type.CHAR) + || type.equals(Type.BYTE) + || type.equals(Type.SHORT)) { + type = Type.INT; + } + this.stack().push(type); + } + + @Override + public void visitCASTORE(CASTORE cASTORE) { + this.stack().pop(); + this.stack().pop(); + this.stack().pop(); + } + + @Override + public void visitLSHR(LSHR lSHR) { + this.stack().pop(); + this.stack().pop(); + this.stack().push(Type.LONG); + } + + @Override + public void visitSASTORE(SASTORE sASTORE) { + this.stack().pop(); + this.stack().pop(); + this.stack().pop(); + } + + @Override + public void visitISHR(ISHR sHR) { + this.stack().pop(); + this.stack().pop(); + this.stack().push(Type.INT); + } + + @Override + public void visitPOP2(POP2 pOP2) { + if (this.stack().pop().getSize() == 1) { + this.stack().pop(); + } + } + + @Override + public void visitLXOR(LXOR lXOR) { + this.stack().pop(); + this.stack().pop(); + this.stack().push(Type.LONG); + } + + @Override + public void visitNEW(NEW nEW) { + this.stack().push(new UninitializedObjectType((ObjectType) nEW.getType(this.cpg))); + } + + @Override + public void visitLCONST(LCONST lCONST) { + this.stack().push(Type.LONG); + } + + @Override + public void visitFREM(FREM fREM) { + this.stack().pop(); + this.stack().pop(); + this.stack().push(Type.FLOAT); + } + + @Override + public void visitIFGE(IFGE fGE) { + this.stack().pop(); + } + + @Override + public void visitILOAD(ILOAD lOAD) { + this.stack().push(Type.INT); + } + + @Override + public void visitIFNE(IFNE fNE) { + this.stack().pop(); + } + + @Override + public void visitDDIV(DDIV dDIV) { + this.stack().pop(); + this.stack().pop(); + this.stack().push(Type.DOUBLE); + } + + @Override + public void visitIFEQ(IFEQ fEQ) { + this.stack().pop(); + } + + @Override + public void visitPUTFIELD(PUTFIELD pUTFIELD) { + this.stack().pop(); + this.stack().pop(); + } + + @Override + public void visitF2L(F2L f2L) { + this.stack().pop(); + this.stack().push(Type.LONG); + } + + @Override + public void visitD2F(D2F d2F) { + this.stack().pop(); + this.stack().push(Type.FLOAT); + } + + @Override + public void visitLSUB(LSUB lSUB) { + this.stack().pop(); + this.stack().pop(); + this.stack().push(Type.LONG); + } + + @Override + public void visitLCMP(LCMP lCMP) { + this.stack().pop(); + this.stack().pop(); + this.stack().push(Type.INT); + } + + @Override + public void visitTABLESWITCH(TABLESWITCH tABLESWITCH) { + this.stack().pop(); + } + + @Override + public void visitCHECKCAST(CHECKCAST cHECKCAST) { + this.stack().pop(); + this.stack().push(cHECKCAST.getType(this.cpg)); + } + + @Override + public void visitATHROW(ATHROW aTHROW) { + Type type = this.stack().pop(); + this.stack().clear(); + if (type.equals(Type.NULL)) { + this.stack().push(Type.getType("Ljava/lang/NullPointerException;")); + } else { + this.stack().push(type); + } + } + + @Override + public void visitFASTORE(FASTORE fASTORE) { + this.stack().pop(); + this.stack().pop(); + this.stack().pop(); + } + + public LocalVariables locals() { + return this.frame.getLocals(); + } + + @Override + public void visitIXOR(IXOR xOR) { + this.stack().pop(); + this.stack().pop(); + this.stack().push(Type.INT); + } + + @Override + public void visitIF_ACMPEQ(IF_ACMPEQ f_ACMPEQ) { + this.stack().pop(); + this.stack().pop(); + } + + @Override + public void visitINEG(INEG nEG) { + this.stack().pop(); + this.stack().push(Type.INT); + } + + @Override + public void visitASTORE(ASTORE aSTORE) { + this.locals().set(aSTORE.getIndex(), this.stack().pop()); + } + + @Override + public void visitINVOKESPECIAL(INVOKESPECIAL nVOKESPECIAL) { + if (nVOKESPECIAL.getText4(this.cpg).equals("")) { + UninitializedObjectType uninitializedObjectType; + if ((uninitializedObjectType = + (UninitializedObjectType) + this.stack().peek(nVOKESPECIAL.getArgumentTypes(this.cpg).length)) + == Frame._this) { + Frame._this = null; + } + this.stack().initializeObject(uninitializedObjectType); + this.locals().initializeObject(uninitializedObjectType); + } + this.stack().pop(); + int value = 0; + for (int value2 = value; + value2 < nVOKESPECIAL.getArgumentTypes(this.cpg).length; + value2 = value) { + value++; + this.stack().pop(); + } + if (nVOKESPECIAL.getType2(this.cpg) != Type.VOID) { + Type type; + if ((type = nVOKESPECIAL.getType2(this.cpg)).equals(Type.BOOLEAN) + || type.equals(Type.CHAR) + || type.equals(Type.BYTE) + || type.equals(Type.SHORT)) { + type = Type.INT; + } + this.stack().push(type); + } + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/structurals/Frame.java b/src/main/java/com/allatori/lib/bcel/verifier/structurals/Frame.java new file mode 100644 index 0000000..d482ab4 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/structurals/Frame.java @@ -0,0 +1,53 @@ +package com.allatori.lib.bcel.verifier.structurals; + +public class Frame { + + public static UninitializedObjectType _this; + + public LocalVariables locals; + + public OperandStack stack; + + public OperandStack getStack() { + return this.stack; + } + + public LocalVariables getLocals() { + return this.locals; + } + + @Override + public boolean equals(Object result) { + if (!(result instanceof Frame)) { + return false; + } + Frame frame = (Frame) result; + return this.stack.equals(frame.stack) && this.locals.equals(frame.locals); + } + + @Override + public int hashCode() { + return this.stack.hashCode() ^ this.locals.hashCode(); + } + + public Frame(LocalVariables localVariables, OperandStack operandStack) { + super(); + this.locals = localVariables; + this.stack = operandStack; + } + + @Override + public Object clone() { + return new Frame(this.locals.getClone(), this.stack.getClone()); + } + + public Frame getClone() { + return (Frame) this.clone(); + } + + public Frame(int value, int value2) { + super(); + this.locals = new LocalVariables(value); + this.stack = new OperandStack(value2); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/structurals/GenericArray.java b/src/main/java/com/allatori/lib/bcel/verifier/structurals/GenericArray.java new file mode 100644 index 0000000..af1ad71 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/structurals/GenericArray.java @@ -0,0 +1,11 @@ +package com.allatori.lib.bcel.verifier.structurals; + +import java.io.Serializable; + +public class GenericArray implements Cloneable, Serializable { + + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/structurals/InstConstraintVisitor.java b/src/main/java/com/allatori/lib/bcel/verifier/structurals/InstConstraintVisitor.java new file mode 100644 index 0000000..d4c0cc1 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/structurals/InstConstraintVisitor.java @@ -0,0 +1,3162 @@ +package com.allatori.lib.bcel.verifier.structurals; + +import com.allatori.lib.bcel.Repository; +import com.allatori.lib.bcel.classfile.Constant; +import com.allatori.lib.bcel.classfile.ConstantClass; +import com.allatori.lib.bcel.classfile.ConstantDouble; +import com.allatori.lib.bcel.classfile.ConstantFieldref; +import com.allatori.lib.bcel.classfile.ConstantFloat; +import com.allatori.lib.bcel.classfile.ConstantInteger; +import com.allatori.lib.bcel.classfile.ConstantLong; +import com.allatori.lib.bcel.classfile.ConstantString; +import com.allatori.lib.bcel.classfile.Field; +import com.allatori.lib.bcel.classfile.JavaClass; +import com.allatori.lib.bcel.generic.AALOAD; +import com.allatori.lib.bcel.generic.AASTORE; +import com.allatori.lib.bcel.generic.ACONST_NULL; +import com.allatori.lib.bcel.generic.ALOAD; +import com.allatori.lib.bcel.generic.ANEWARRAY; +import com.allatori.lib.bcel.generic.ARETURN; +import com.allatori.lib.bcel.generic.ARRAYLENGTH; +import com.allatori.lib.bcel.generic.ASTORE; +import com.allatori.lib.bcel.generic.ATHROW; +import com.allatori.lib.bcel.generic.ArrayType; +import com.allatori.lib.bcel.generic.BALOAD; +import com.allatori.lib.bcel.generic.BASTORE; +import com.allatori.lib.bcel.generic.BIPUSH; +import com.allatori.lib.bcel.generic.BREAKPOINT; +import com.allatori.lib.bcel.generic.CALOAD; +import com.allatori.lib.bcel.generic.CASTORE; +import com.allatori.lib.bcel.generic.CHECKCAST; +import com.allatori.lib.bcel.generic.CPInstruction; +import com.allatori.lib.bcel.generic.ConstantPoolGen; +import com.allatori.lib.bcel.generic.D2F; +import com.allatori.lib.bcel.generic.D2I; +import com.allatori.lib.bcel.generic.D2L; +import com.allatori.lib.bcel.generic.DADD; +import com.allatori.lib.bcel.generic.DALOAD; +import com.allatori.lib.bcel.generic.DASTORE; +import com.allatori.lib.bcel.generic.DCMPG; +import com.allatori.lib.bcel.generic.DCMPL; +import com.allatori.lib.bcel.generic.DCONST; +import com.allatori.lib.bcel.generic.DDIV; +import com.allatori.lib.bcel.generic.DLOAD; +import com.allatori.lib.bcel.generic.DMUL; +import com.allatori.lib.bcel.generic.DNEG; +import com.allatori.lib.bcel.generic.DREM; +import com.allatori.lib.bcel.generic.DRETURN; +import com.allatori.lib.bcel.generic.DSTORE; +import com.allatori.lib.bcel.generic.DSUB; +import com.allatori.lib.bcel.generic.DUP; +import com.allatori.lib.bcel.generic.DUP2; +import com.allatori.lib.bcel.generic.DUP2_X1; +import com.allatori.lib.bcel.generic.DUP2_X2; +import com.allatori.lib.bcel.generic.DUP_X1; +import com.allatori.lib.bcel.generic.DUP_X2; +import com.allatori.lib.bcel.generic.EmptyVisitor; +import com.allatori.lib.bcel.generic.F2D; +import com.allatori.lib.bcel.generic.F2I; +import com.allatori.lib.bcel.generic.F2L; +import com.allatori.lib.bcel.generic.FADD; +import com.allatori.lib.bcel.generic.FALOAD; +import com.allatori.lib.bcel.generic.FASTORE; +import com.allatori.lib.bcel.generic.FCMPG; +import com.allatori.lib.bcel.generic.FCMPL; +import com.allatori.lib.bcel.generic.FCONST; +import com.allatori.lib.bcel.generic.FDIV; +import com.allatori.lib.bcel.generic.FLOAD; +import com.allatori.lib.bcel.generic.FMUL; +import com.allatori.lib.bcel.generic.FNEG; +import com.allatori.lib.bcel.generic.FREM; +import com.allatori.lib.bcel.generic.FRETURN; +import com.allatori.lib.bcel.generic.FSTORE; +import com.allatori.lib.bcel.generic.FSUB; +import com.allatori.lib.bcel.generic.FieldInstruction; +import com.allatori.lib.bcel.generic.GETFIELD; +import com.allatori.lib.bcel.generic.GETSTATIC; +import com.allatori.lib.bcel.generic.GOTO; +import com.allatori.lib.bcel.generic.GOTO_W; +import com.allatori.lib.bcel.generic.I2B; +import com.allatori.lib.bcel.generic.I2C; +import com.allatori.lib.bcel.generic.I2D; +import com.allatori.lib.bcel.generic.I2F; +import com.allatori.lib.bcel.generic.I2L; +import com.allatori.lib.bcel.generic.I2S; +import com.allatori.lib.bcel.generic.IADD; +import com.allatori.lib.bcel.generic.IALOAD; +import com.allatori.lib.bcel.generic.IAND; +import com.allatori.lib.bcel.generic.IASTORE; +import com.allatori.lib.bcel.generic.ICONST; +import com.allatori.lib.bcel.generic.IDIV; +import com.allatori.lib.bcel.generic.IFEQ; +import com.allatori.lib.bcel.generic.IFGE; +import com.allatori.lib.bcel.generic.IFGT; +import com.allatori.lib.bcel.generic.IFLE; +import com.allatori.lib.bcel.generic.IFLT; +import com.allatori.lib.bcel.generic.IFNE; +import com.allatori.lib.bcel.generic.IFNONNULL; +import com.allatori.lib.bcel.generic.IFNULL; +import com.allatori.lib.bcel.generic.IF_ACMPEQ; +import com.allatori.lib.bcel.generic.IF_ACMPNE; +import com.allatori.lib.bcel.generic.IF_ICMPEQ; +import com.allatori.lib.bcel.generic.IF_ICMPGE; +import com.allatori.lib.bcel.generic.IF_ICMPGT; +import com.allatori.lib.bcel.generic.IF_ICMPLE; +import com.allatori.lib.bcel.generic.IF_ICMPLT; +import com.allatori.lib.bcel.generic.IF_ICMPNE; +import com.allatori.lib.bcel.generic.IINC; +import com.allatori.lib.bcel.generic.ILOAD; +import com.allatori.lib.bcel.generic.IMPDEP1; +import com.allatori.lib.bcel.generic.IMPDEP2; +import com.allatori.lib.bcel.generic.IMUL; +import com.allatori.lib.bcel.generic.INEG; +import com.allatori.lib.bcel.generic.INSTANCEOF; +import com.allatori.lib.bcel.generic.INVOKEINTERFACE; +import com.allatori.lib.bcel.generic.INVOKESPECIAL; +import com.allatori.lib.bcel.generic.INVOKESTATIC; +import com.allatori.lib.bcel.generic.INVOKEVIRTUAL; +import com.allatori.lib.bcel.generic.IOR; +import com.allatori.lib.bcel.generic.IREM; +import com.allatori.lib.bcel.generic.IRETURN; +import com.allatori.lib.bcel.generic.ISHL; +import com.allatori.lib.bcel.generic.ISHR; +import com.allatori.lib.bcel.generic.ISTORE; +import com.allatori.lib.bcel.generic.ISUB; +import com.allatori.lib.bcel.generic.IUSHR; +import com.allatori.lib.bcel.generic.IXOR; +import com.allatori.lib.bcel.generic.Instruction; +import com.allatori.lib.bcel.generic.InvokeInstruction; +import com.allatori.lib.bcel.generic.JSR; +import com.allatori.lib.bcel.generic.JSR_W; +import com.allatori.lib.bcel.generic.L2D; +import com.allatori.lib.bcel.generic.L2F; +import com.allatori.lib.bcel.generic.L2I; +import com.allatori.lib.bcel.generic.LADD; +import com.allatori.lib.bcel.generic.LALOAD; +import com.allatori.lib.bcel.generic.LAND; +import com.allatori.lib.bcel.generic.LASTORE; +import com.allatori.lib.bcel.generic.LCMP; +import com.allatori.lib.bcel.generic.LCONST; +import com.allatori.lib.bcel.generic.LDC; +import com.allatori.lib.bcel.generic.LDC2_W; +import com.allatori.lib.bcel.generic.LDC_W; +import com.allatori.lib.bcel.generic.LDIV; +import com.allatori.lib.bcel.generic.LLOAD; +import com.allatori.lib.bcel.generic.LMUL; +import com.allatori.lib.bcel.generic.LNEG; +import com.allatori.lib.bcel.generic.LOOKUPSWITCH; +import com.allatori.lib.bcel.generic.LOR; +import com.allatori.lib.bcel.generic.LREM; +import com.allatori.lib.bcel.generic.LRETURN; +import com.allatori.lib.bcel.generic.LSHL; +import com.allatori.lib.bcel.generic.LSHR; +import com.allatori.lib.bcel.generic.LSTORE; +import com.allatori.lib.bcel.generic.LSUB; +import com.allatori.lib.bcel.generic.LUSHR; +import com.allatori.lib.bcel.generic.LXOR; +import com.allatori.lib.bcel.generic.LoadClass; +import com.allatori.lib.bcel.generic.LoadInstruction; +import com.allatori.lib.bcel.generic.LocalVariableInstruction; +import com.allatori.lib.bcel.generic.MONITORENTER; +import com.allatori.lib.bcel.generic.MONITOREXIT; +import com.allatori.lib.bcel.generic.MULTIANEWARRAY; +import com.allatori.lib.bcel.generic.MethodGen; +import com.allatori.lib.bcel.generic.NEW; +import com.allatori.lib.bcel.generic.NEWARRAY; +import com.allatori.lib.bcel.generic.NOP; +import com.allatori.lib.bcel.generic.ObjectType; +import com.allatori.lib.bcel.generic.POP; +import com.allatori.lib.bcel.generic.POP2; +import com.allatori.lib.bcel.generic.PUTFIELD; +import com.allatori.lib.bcel.generic.PUTSTATIC; +import com.allatori.lib.bcel.generic.RET; +import com.allatori.lib.bcel.generic.RETURN; +import com.allatori.lib.bcel.generic.ReferenceType; +import com.allatori.lib.bcel.generic.ReturnInstruction; +import com.allatori.lib.bcel.generic.ReturnaddressType; +import com.allatori.lib.bcel.generic.SALOAD; +import com.allatori.lib.bcel.generic.SASTORE; +import com.allatori.lib.bcel.generic.SIPUSH; +import com.allatori.lib.bcel.generic.SWAP; +import com.allatori.lib.bcel.generic.StackConsumer; +import com.allatori.lib.bcel.generic.StackInstruction; +import com.allatori.lib.bcel.generic.StackProducer; +import com.allatori.lib.bcel.generic.StoreInstruction; +import com.allatori.lib.bcel.generic.TABLESWITCH; +import com.allatori.lib.bcel.generic.Type; +import com.allatori.lib.bcel.generic.Visitor; +import com.allatori.lib.bcel.verifier.VerificationResult; +import com.allatori.lib.bcel.verifier.VerifierFactory; +import com.allatori.lib.bcel.verifier.exc.AssertionViolatedException; +import com.allatori.lib.bcel.verifier.exc.StructuralCodeConstraintException; + +public class InstConstraintVisitor extends EmptyVisitor implements Visitor { + + public MethodGen mg; + + public ConstantPoolGen cpg; + + public static ObjectType GENERIC_ARRAY = + new ObjectType("com.allatori.lib.bcel.verifier.structurals.GenericArray"); + + public Frame frame = null; + + @Override + public void visitIFGE(IFGE fGE) { + if (this.stack().peek() != Type.INT) { + this.constraintViolated( + fGE, + "The value at the stack top is not of type 'int', but of type '" + + this.stack().peek() + + "'."); + } + } + + @Override + public void visitINSTANCEOF(INSTANCEOF nSTANCEOF) { + Type type; + if (!((type = this.stack().peek(0)) instanceof ReferenceType)) { + this.constraintViolated( + nSTANCEOF, "The 'objectref' is not of a ReferenceType but of type " + type + "."); + } + Constant constant; + if (!((constant = this.cpg.getConstant(nSTANCEOF.getIndex())) instanceof ConstantClass)) { + this.constraintViolated( + nSTANCEOF, "The Constant at 'index' is not a ConstantClass, but '" + constant + "'."); + } + } + + @Override + public void visitLCMP(LCMP lCMP) { + if (this.stack().peek() != Type.LONG) { + this.constraintViolated( + lCMP, + "The value at the stack top is not of type 'long', but of type '" + + this.stack().peek() + + "'."); + } + if (this.stack().peek(1) != Type.LONG) { + this.constraintViolated( + lCMP, + "The value at the stack next-to-top is not of type 'long', but of type '" + + this.stack().peek(1) + + "'."); + } + } + + @Override + public void visitFNEG(FNEG fNEG) { + if (this.stack().peek() != Type.FLOAT) { + this.constraintViolated( + fNEG, + "The value at the stack top is not of type 'float', but of type '" + + this.stack().peek() + + "'."); + } + } + + @Override + public void visitGETSTATIC(GETSTATIC gETSTATIC) {} + + @Override + public void visitLASTORE(LASTORE lASTORE) { + if (this.stack().peek() != Type.LONG) { + this.constraintViolated( + lASTORE, + "The value at the stack top is not of type 'long', but of type '" + + this.stack().peek() + + "'."); + } + this.processType2(lASTORE, this.stack().peek(1)); + if (this.stack().peek(2) != Type.NULL) { + if (!(this.stack().peek(2) instanceof ArrayType)) { + this.constraintViolated( + lASTORE, + "Stack next-to-next-to-top must be of type long[] but is '" + + this.stack().peek(2) + + "'."); + } + if (((ArrayType) this.stack().peek(2)).getBasicType() != Type.LONG) { + this.constraintViolated( + lASTORE, + "Stack next-to-next-to-top must be of type long[] but is '" + + this.stack().peek(2) + + "'."); + } + } + } + + public void setFrame(Frame frame2) { + this.frame = frame2; + } + + @Override + public void visitDUP2_X1(DUP2_X1 dUP2_X1) { + if (this.stack().peek().getSize() == 2) { + if (this.stack().peek(1).getSize() != 1) { + this.constraintViolated( + dUP2_X1, + "If stack top's size is 2, then stack next-to-top's size must be 1. But it is '" + + this.stack().peek(1) + + "' of size '" + + this.stack().peek(1).getSize() + + "'."); + } + } else { + if (this.stack().peek(1).getSize() != 1) { + this.constraintViolated( + dUP2_X1, + "If stack top's size is 1, then stack next-to-top's size must also be 1. But it is '" + + this.stack().peek(1) + + "' of size '" + + this.stack().peek(1).getSize() + + "'."); + } + if (this.stack().peek(2).getSize() != 1) { + this.constraintViolated( + dUP2_X1, + "If stack top's size is 1, then stack next-to-next-to-top's size must also be 1. But it" + + " is '" + + this.stack().peek(2) + + "' of size '" + + this.stack().peek(2).getSize() + + "'."); + } + } + } + + @Override + public void visitDREM(DREM dREM) { + if (this.stack().peek() != Type.DOUBLE) { + this.constraintViolated( + dREM, + "The value at the stack top is not of type 'double', but of type '" + + this.stack().peek() + + "'."); + } + if (this.stack().peek(1) != Type.DOUBLE) { + this.constraintViolated( + dREM, + "The value at the stack next-to-top is not of type 'double', but of type '" + + this.stack().peek(1) + + "'."); + } + } + + public void referenceTypeIsInitialized(Instruction instruction, ReferenceType referenceType) { + if (referenceType instanceof UninitializedObjectType) { + this.constraintViolated( + instruction, "Working on an uninitialized object '" + referenceType + "'."); + } + } + + @Override + public void visitLoadInstruction(LoadInstruction loadInstruction) { + if (this.locals().get(loadInstruction.getIndex()) == Type.UNKNOWN) { + this.constraintViolated( + loadInstruction, + "Read-Access on local variable " + loadInstruction.getIndex() + " with unknown content."); + } + if (loadInstruction.getType(this.cpg).getSize() == 2 + && this.locals().get(loadInstruction.getIndex() + 1) != Type.UNKNOWN) { + this.constraintViolated( + loadInstruction, + "Reading a two-locals value from local variables " + + loadInstruction.getIndex() + + " and " + + (loadInstruction.getIndex() + 1) + + " where the latter one is destroyed."); + } + InstConstraintVisitor instConstraintVisitor; + label26: + { + if (!(loadInstruction instanceof ALOAD)) { + if (this.locals().get(loadInstruction.getIndex()) != loadInstruction.getType(this.cpg)) { + StringBuilder stringBuilder = + new StringBuilder() + .insert( + 0, + "Local Variable type and LOADing Instruction type mismatch: Local Variable:" + + " '"); + instConstraintVisitor = this; + this.constraintViolated( + loadInstruction, + stringBuilder + .append(this.locals().get(loadInstruction.getIndex())) + .append("'; Instruction type: '") + .append(loadInstruction.getType(this.cpg)) + .append("'.") + .toString()); + break label26; + } + } else if (!(this.locals().get(loadInstruction.getIndex()) instanceof ReferenceType)) { + this.constraintViolated( + loadInstruction, + "Local Variable type and LOADing Instruction type mismatch: Local Variable: '" + + this.locals().get(loadInstruction.getIndex()) + + "'; Instruction expects a ReferenceType."); + } + instConstraintVisitor = this; + } + if (instConstraintVisitor.stack().maxStack() - this.stack().slotsUsed() + < loadInstruction.getType(this.cpg).getSize()) { + this.constraintViolated( + loadInstruction, + "Not enough free stack slots to load a '" + + loadInstruction.getType(this.cpg) + + "' onto the OperandStack."); + } + } + + @Override + public void visitDNEG(DNEG dNEG) { + if (this.stack().peek() != Type.DOUBLE) { + this.constraintViolated( + dNEG, + "The value at the stack top is not of type 'double', but of type '" + + this.stack().peek() + + "'."); + } + } + + @Override + public void visitStackProducer(StackProducer stackProducer) { + this._visitStackAccessor((Instruction) stackProducer); + } + + @Override + public void visitI2B(I2B i2B) { + if (this.stack().peek() != Type.INT) { + this.constraintViolated( + i2B, + "The value at the stack top is not of type 'int', but of type '" + + this.stack().peek() + + "'."); + } + } + + @Override + public void visitL2I(L2I l2I) { + if (this.stack().peek() != Type.LONG) { + this.constraintViolated( + l2I, + "The value at the stack top is not of type 'long', but of type '" + + this.stack().peek() + + "'."); + } + } + + @Override + public void visitIALOAD(IALOAD aLOAD) { + this.processType2(aLOAD, this.stack().peek()); + if (this.stack().peek(1) != Type.NULL) { + if (!(this.stack().peek(1) instanceof ArrayType)) { + this.constraintViolated( + aLOAD, + "Stack next-to-top must be of type int[] but is '" + this.stack().peek(1) + "'."); + } + if (((ArrayType) this.stack().peek(1)).getBasicType() != Type.INT) { + this.constraintViolated( + aLOAD, + "Stack next-to-top must be of type int[] but is '" + this.stack().peek(1) + "'."); + } + } + } + + @Override + public void visitFMUL(FMUL fMUL) { + if (this.stack().peek() != Type.FLOAT) { + this.constraintViolated( + fMUL, + "The value at the stack top is not of type 'float', but of type '" + + this.stack().peek() + + "'."); + } + if (this.stack().peek(1) != Type.FLOAT) { + this.constraintViolated( + fMUL, + "The value at the stack next-to-top is not of type 'float', but of type '" + + this.stack().peek(1) + + "'."); + } + } + + @Override + public void visitLLOAD(LLOAD lLOAD) {} + + @Override + public void visitDUP_X1(DUP_X1 dUP_X1) { + if (this.stack().peek().getSize() != 1) { + this.constraintViolated( + dUP_X1, + "Type on stack top '" + + this.stack().peek() + + "' should occupy exactly one slot, not '" + + this.stack().peek().getSize() + + "'."); + } + if (this.stack().peek(1).getSize() != 1) { + this.constraintViolated( + dUP_X1, + "Type on stack next-to-top '" + + this.stack().peek(1) + + "' should occupy exactly one slot, not '" + + this.stack().peek(1).getSize() + + "'."); + } + } + + @Override + public void visitPOP2(POP2 pOP2) { + if (this.stack().peek().getSize() != 2) { + this.constraintViolated( + pOP2, + "Stack top size should be 2 but stack top is '" + + this.stack().peek() + + "' of size '" + + this.stack().peek().getSize() + + "'."); + } + } + + @Override + public void visitFCONST(FCONST fCONST) {} + + @Override + public void visitLDC2_W(LDC2_W lDC2_W) { + Constant constant; + if (!((constant = this.cpg.getConstant(lDC2_W.getIndex())) instanceof ConstantLong) + && !(constant instanceof ConstantDouble)) { + this.constraintViolated( + lDC2_W, + "Referenced constant should be a CONSTANT_Integer, a CONSTANT_Float or a CONSTANT_String," + + " but is '" + + constant + + "'."); + } + } + + @Override + public void visitPUTSTATIC(PUTSTATIC pUTSTATIC) { + Field field; + try { + String fieldName = pUTSTATIC.getFieldName(this.cpg); + Field[] fields = + Repository.lookupClass(pUTSTATIC.createObjectType(this.cpg).getClassName()).getFields(); + Field field2 = null; + int value; + int value2 = value = 0; + while (true) { + if (value2 >= fields.length) { + field = field2; + break; + } + if (fields[value].getText().equals(fieldName)) { + Type type = Type.getType(fields[value].getText2()); + Type type2 = pUTSTATIC.getType(this.cpg); + if (type.equals(type2)) { + field = field2 = fields[value]; + break; + } + } + value2 = ++value; + } + if (field == null) { + throw new AssertionViolatedException("Field not found?!?"); + } + Type type3 = this.stack().peek(); + Type type4; + Type type5 = type4 = Type.getType(field2.getText2()); + if (type5 == Type.BOOLEAN + || type5 == Type.BYTE + || type5 == Type.CHAR + || type5 == Type.SHORT) { + type5 = Type.INT; + } + if (type4 instanceof ReferenceType) { + ReferenceType referenceType; + if (type3 instanceof ReferenceType) { + ReferenceType referenceType2 = (ReferenceType) type3; + referenceType = referenceType2; + this.referenceTypeIsInitialized(pUTSTATIC, referenceType2); + } else { + this.constraintViolated( + pUTSTATIC, + "The stack top type '" + type3 + "' is not of a reference type as expected."); + referenceType = (ReferenceType) (Object) null; + } + if (!referenceType.matchesType2(type5)) { + this.constraintViolated( + pUTSTATIC, + "The stack top type '" + + type3 + + "' is not assignment compatible with '" + + type5 + + "'."); + return; + } + } else if (type5 != type3) { + this.constraintViolated( + pUTSTATIC, + "The stack top type '" + type3 + "' is not of type '" + type5 + "' as expected."); + return; + } + } catch (ClassNotFoundException classNotFoundException) { + throw new AssertionViolatedException(("Missing class: " + classNotFoundException.toString())); + } + } + + public void constraintViolated(Instruction instruction, String text) { + String name = instruction.getClass().getName(); + throw new StructuralCodeConstraintException( + ("Instruction " + + name.substring(name.lastIndexOf(46) + 1) + + " constraint violated: " + + text)); + } + + @Override + public void visitBASTORE(BASTORE bASTORE) { + Type type = this.stack().peek(2); + Type type2 = this.stack().peek(1); + Type type3 = this.stack().peek(0); + this.processType2(bASTORE, type2); + this.processType(bASTORE, type3); + if (this.arrayrefOfArrayType(bASTORE, type) + && !((ArrayType) type).getElementType().equals(Type.BOOLEAN) + && !((ArrayType) type).getElementType().equals(Type.BYTE)) { + this.constraintViolated( + bASTORE, + "The 'arrayref' does not refer to an array with elements of a Type.BYTE or Type.BOOLEAN" + + " but to an array of '" + + ((ArrayType) type).getElementType() + + "'."); + } + } + + @Override + public void visitAALOAD(AALOAD aALOAD) { + Type type = this.stack().peek(1); + Type type2 = this.stack().peek(0); + this.processType2(aALOAD, type2); + if (this.arrayrefOfArrayType(aALOAD, type) + && !(((ArrayType) type).getElementType() instanceof ReferenceType)) { + this.constraintViolated( + aALOAD, + "The 'arrayref' does not refer to an array with elements of a ReferenceType but to an" + + " array of " + + ((ArrayType) type).getElementType() + + "."); + } + } + + @Override + public void visitARRAYLENGTH(ARRAYLENGTH aRRAYLENGTH) { + Type type = this.stack().peek(0); + this.arrayrefOfArrayType(aRRAYLENGTH, type); + } + + @Override + public void visitDSTORE(DSTORE dSTORE) {} + + @Override + public void visitATHROW(ATHROW aTHROW) { + try { + if (!(this.stack().peek() instanceof ObjectType) && !this.stack().peek().equals(Type.NULL)) { + this.constraintViolated( + aTHROW, + "The 'objectref' is not of an (initialized) ObjectType but of type " + + this.stack().peek() + + "."); + } + if (!this.stack().peek().equals(Type.NULL)) { + ObjectType objectType = (ObjectType) this.stack().peek(); + ObjectType objectType2 = (ObjectType) Type.getType("Ljava/lang/Throwable;"); + if (!objectType.matchesObjectType(objectType2) && !objectType.equals(objectType2)) { + this.constraintViolated( + aTHROW, + "The 'objectref' is not of class Throwable or of a subclass of Throwable, but of '" + + this.stack().peek() + + "'."); + } + } + } catch (ClassNotFoundException classNotFoundException) { + throw new AssertionViolatedException(("Missing class: " + classNotFoundException.toString())); + } + } + + @Override + public void visitI2S(I2S i2S) { + if (this.stack().peek() != Type.INT) { + this.constraintViolated( + i2S, + "The value at the stack top is not of type 'int', but of type '" + + this.stack().peek() + + "'."); + } + } + + @Override + public void visitINVOKESTATIC(INVOKESTATIC nVOKESTATIC) { + try { + VerificationResult verificationResult; + String text; + Type type; + if ((type = nVOKESTATIC.getType(this.cpg)) instanceof ObjectType + && (verificationResult = + VerifierFactory.getVerifier(text = ((ObjectType) type).getClassName()) + .createVerificationResult2()) + .getStatus() + != 1) { + this.constraintViolated( + nVOKESTATIC, + "Class '" + + text + + "' is referenced, but cannot be loaded and resolved: '" + + verificationResult + + "'."); + } + int value; + Type[] types; + for (int value2 = (value = (types = nVOKESTATIC.getArgumentTypes(this.cpg)).length) - 1; + value2 >= 0; + value2--) { + Type type2 = this.stack().peek(value - 1 - value2); + Type type3; + if ((type3 = types[value2]) == Type.BOOLEAN + || type3 == Type.BYTE + || type3 == Type.CHAR + || type3 == Type.SHORT) { + type3 = Type.INT; + } + if (!type2.equals(type3)) { + if (type2 instanceof ReferenceType && type3 instanceof ReferenceType) { + ReferenceType referenceType = (ReferenceType) type2; + ReferenceType referenceType2 = (ReferenceType) type3; + if (!referenceType.matchesType2(referenceType2)) { + this.constraintViolated( + nVOKESTATIC, + "Expecting a '" + + type3 + + "' but found a '" + + type2 + + "' on the stack (which is not assignment compatible)."); + } + this.referenceTypeIsInitialized(nVOKESTATIC, referenceType); + } else { + this.constraintViolated( + nVOKESTATIC, + "Expecting a '" + type3 + "' but found a '" + type2 + "' on the stack."); + } + } + } + } catch (ClassNotFoundException classNotFoundException) { + throw new AssertionViolatedException(("Missing class: " + classNotFoundException.toString())); + } + } + + @Override + public void visitIF_ICMPNE(IF_ICMPNE f_ICMPNE) { + if (this.stack().peek() != Type.INT) { + this.constraintViolated( + f_ICMPNE, + "The value at the stack top is not of type 'int', but of type '" + + this.stack().peek() + + "'."); + } + if (this.stack().peek(1) != Type.INT) { + this.constraintViolated( + f_ICMPNE, + "The value at the stack next-to-top is not of type 'int', but of type '" + + this.stack().peek(1) + + "'."); + } + } + + @Override + public void visitFSUB(FSUB fSUB) { + if (this.stack().peek() != Type.FLOAT) { + this.constraintViolated( + fSUB, + "The value at the stack top is not of type 'float', but of type '" + + this.stack().peek() + + "'."); + } + if (this.stack().peek(1) != Type.FLOAT) { + this.constraintViolated( + fSUB, + "The value at the stack next-to-top is not of type 'float', but of type '" + + this.stack().peek(1) + + "'."); + } + } + + @Override + public void visitDCONST(DCONST dCONST) {} + + @Override + public void visitLocalVariableInstruction(LocalVariableInstruction localVariableInstruction) { + if (this.locals().getLocals() + <= (localVariableInstruction.getType(this.cpg).getSize() == 1 + ? localVariableInstruction.getIndex() + : localVariableInstruction.getIndex() + 1)) { + this.constraintViolated( + localVariableInstruction, + "The 'index' is not a valid index into the local variable array."); + } + } + + @Override + public void visitINVOKEVIRTUAL(INVOKEVIRTUAL nVOKEVIRTUAL) { + try { + String text; + VerificationResult verificationResult; + Type type; + if ((type = nVOKEVIRTUAL.getType(this.cpg)) instanceof ObjectType + && (verificationResult = + VerifierFactory.getVerifier(text = ((ObjectType) type).getClassName()) + .createVerificationResult2()) + .getStatus() + != 1) { + this.constraintViolated( + nVOKEVIRTUAL, + "Class '" + + text + + "' is referenced, but cannot be loaded and resolved: '" + + verificationResult + + "'."); + } + Type[] types; + int value; + int value2; + for (int value3 = + value = (value2 = (types = nVOKEVIRTUAL.getArgumentTypes(this.cpg)).length) - 1; + value3 >= 0; + value3 = --value) { + Type type2 = this.stack().peek(value2 - 1 - value); + Type type3; + if ((type3 = types[value]) == Type.BOOLEAN + || type3 == Type.BYTE + || type3 == Type.CHAR + || type3 == Type.SHORT) { + type3 = Type.INT; + } + if (!type2.equals(type3)) { + if (type2 instanceof ReferenceType && type3 instanceof ReferenceType) { + ReferenceType referenceType = (ReferenceType) type2; + ReferenceType referenceType2 = (ReferenceType) type3; + if (!referenceType.matchesType2(referenceType2)) { + this.constraintViolated( + nVOKEVIRTUAL, + "Expecting a '" + + type3 + + "' but found a '" + + type2 + + "' on the stack (which is not assignment compatible)."); + } + this.referenceTypeIsInitialized(nVOKEVIRTUAL, referenceType); + } else { + this.constraintViolated( + nVOKEVIRTUAL, + "Expecting a '" + type3 + "' but found a '" + type2 + "' on the stack."); + } + } + } + Type type4; + if ((type4 = this.stack().peek(value2)) != Type.NULL) { + if (!(type4 instanceof ReferenceType)) { + this.constraintViolated( + nVOKEVIRTUAL, + "Expecting a reference type as 'objectref' on the stack, not a '" + type4 + "'."); + } + Type type5; + label51: + { + this.referenceTypeIsInitialized(nVOKEVIRTUAL, (ReferenceType) type4); + if (!(type4 instanceof ObjectType)) { + if (!(type4 instanceof ArrayType)) { + type5 = type4; + this.constraintViolated( + nVOKEVIRTUAL, + "Expecting an ObjectType as 'objectref' on the stack, not a '" + type4 + "'."); + break label51; + } + type4 = GENERIC_ARRAY; + } + type5 = type4; + } + String className = ((ObjectType) type5).getClassName(); + String text2 = nVOKEVIRTUAL.getText2(this.cpg); + if (!Repository.matchesText(className, text2)) { + this.constraintViolated( + nVOKEVIRTUAL, + "The 'objref' item '" + type4 + "' does not implement '" + text2 + "' as expected."); + } + } + } catch (ClassNotFoundException classNotFoundException) { + throw new AssertionViolatedException(("Missing class: " + classNotFoundException.toString())); + } + } + + @Override + public void visitD2I(D2I d2I) { + if (this.stack().peek() != Type.DOUBLE) { + this.constraintViolated( + d2I, + "The value at the stack top is not of type 'double', but of type '" + + this.stack().peek() + + "'."); + } + } + + @Override + public void visitNOP(NOP nOP) {} + + public void visitLDC_W(LDC_W lDC_W) { + Constant constant; + if (!((constant = this.cpg.getConstant(lDC_W.getIndex())) instanceof ConstantInteger) + && !(constant instanceof ConstantFloat) + && !(constant instanceof ConstantString)) { + this.constraintViolated( + lDC_W, + "Referenced constant should be a CONSTANT_Integer, a CONSTANT_Float or a CONSTANT_String," + + " but is '" + + constant + + "'."); + } + } + + @Override + public void visitLXOR(LXOR lXOR) { + if (this.stack().peek() != Type.LONG) { + this.constraintViolated( + lXOR, + "The value at the stack top is not of type 'long', but of type '" + + this.stack().peek() + + "'."); + } + if (this.stack().peek(1) != Type.LONG) { + this.constraintViolated( + lXOR, + "The value at the stack next-to-top is not of type 'long', but of type '" + + this.stack().peek(1) + + "'."); + } + } + + @Override + public void visitLCONST(LCONST lCONST) {} + + @Override + public void visitIF_ACMPEQ(IF_ACMPEQ f_ACMPEQ) { + if (!(this.stack().peek() instanceof ReferenceType)) { + this.constraintViolated( + f_ACMPEQ, + "The value at the stack top is not of a ReferenceType, but of type '" + + this.stack().peek() + + "'."); + } + if (!(this.stack().peek(1) instanceof ReferenceType)) { + this.constraintViolated( + f_ACMPEQ, + "The value at the stack next-to-top is not of a ReferenceType, but of type '" + + this.stack().peek(1) + + "'."); + } + } + + @Override + public void visitI2L(I2L i2L) { + if (this.stack().peek() != Type.INT) { + this.constraintViolated( + i2L, + "The value at the stack top is not of type 'int', but of type '" + + this.stack().peek() + + "'."); + } + } + + @Override + public void visitReturnInstruction(ReturnInstruction returnInstruction) { + Type type; + if ((type = this.mg.getType()) == Type.BOOLEAN + || type == Type.BYTE + || type == Type.SHORT + || type == Type.CHAR) { + type = Type.INT; + } + ReturnInstruction returnInstruction2; + if (returnInstruction instanceof RETURN) { + if (type == Type.VOID) { + return; + } + returnInstruction2 = returnInstruction; + this.constraintViolated(returnInstruction, "RETURN instruction in non-void method."); + } else { + returnInstruction2 = returnInstruction; + } + if (returnInstruction2 instanceof ARETURN) { + if (this.stack().peek() != Type.NULL) { + if (!(this.stack().peek() instanceof ReferenceType)) { + this.constraintViolated( + returnInstruction, + "Reference type expected on top of stack, but is: '" + this.stack().peek() + "'."); + } + this.referenceTypeIsInitialized(returnInstruction, (ReferenceType) this.stack().peek()); + } + } else { + if (!type.equals(this.stack().peek())) { + this.constraintViolated( + returnInstruction, + "Current method has return type of '" + + this.mg.getType() + + "' expecting a '" + + type + + "' on top of the stack. But stack top is a '" + + this.stack().peek() + + "'."); + } + } + } + + @Override + public void visitIFNE(IFNE fNE) { + if (this.stack().peek() != Type.INT) { + this.constraintViolated( + fNE, + "The value at the stack top is not of type 'int', but of type '" + + this.stack().peek() + + "'."); + } + } + + @Override + public void visitDRETURN(DRETURN dRETURN) { + if (this.stack().peek() != Type.DOUBLE) { + this.constraintViolated( + dRETURN, + "The value at the stack top is not of type 'double', but of type '" + + this.stack().peek() + + "'."); + } + } + + @Override + public void visitD2L(D2L d2L) { + if (this.stack().peek() != Type.DOUBLE) { + this.constraintViolated( + d2L, + "The value at the stack top is not of type 'double', but of type '" + + this.stack().peek() + + "'."); + } + } + + @Override + public void visitIREM(IREM rEM) { + if (this.stack().peek() != Type.INT) { + this.constraintViolated( + rEM, + "The value at the stack top is not of type 'int', but of type '" + + this.stack().peek() + + "'."); + } + if (this.stack().peek(1) != Type.INT) { + this.constraintViolated( + rEM, + "The value at the stack next-to-top is not of type 'int', but of type '" + + this.stack().peek(1) + + "'."); + } + } + + @Override + public void visitJSR(JSR jSR) {} + + @Override + public void visitIMPDEP2(IMPDEP2 mPDEP2) { + throw new AssertionViolatedException( + "In this JustIce verification pass there should not occur an illegal instruction such as" + + " IMPDEP2."); + } + + @Override + public void visitSASTORE(SASTORE sASTORE) { + if (this.stack().peek() != Type.INT) { + this.constraintViolated( + sASTORE, + "The value at the stack top is not of type 'int', but of type '" + + this.stack().peek() + + "'."); + } + this.processType2(sASTORE, this.stack().peek(1)); + if (this.stack().peek(2) != Type.NULL) { + if (!(this.stack().peek(2) instanceof ArrayType)) { + this.constraintViolated( + sASTORE, + "Stack next-to-next-to-top must be of type short[] but is '" + + this.stack().peek(2) + + "'."); + } + if (((ArrayType) this.stack().peek(2)).getBasicType() != Type.SHORT) { + this.constraintViolated( + sASTORE, + "Stack next-to-next-to-top must be of type short[] but is '" + + this.stack().peek(2) + + "'."); + } + } + } + + @Override + public void visitCALOAD(CALOAD cALOAD) { + Type type = this.stack().peek(1); + Type type2 = this.stack().peek(0); + this.processType2(cALOAD, type2); + this.arrayrefOfArrayType(cALOAD, type); + } + + @Override + public void visitGOTO_W(GOTO_W gOTO_W) {} + + @Override + public void visitGOTO(GOTO gOTO) {} + + public OperandStack stack() { + return this.frame.getStack(); + } + + @Override + public void visitIASTORE(IASTORE aSTORE) { + if (this.stack().peek() != Type.INT) { + this.constraintViolated( + aSTORE, + "The value at the stack top is not of type 'int', but of type '" + + this.stack().peek() + + "'."); + } + this.processType2(aSTORE, this.stack().peek(1)); + if (this.stack().peek(2) != Type.NULL) { + if (!(this.stack().peek(2) instanceof ArrayType)) { + this.constraintViolated( + aSTORE, + "Stack next-to-next-to-top must be of type int[] but is '" + + this.stack().peek(2) + + "'."); + } + if (((ArrayType) this.stack().peek(2)).getBasicType() != Type.INT) { + this.constraintViolated( + aSTORE, + "Stack next-to-next-to-top must be of type int[] but is '" + + this.stack().peek(2) + + "'."); + } + } + } + + @Override + public void visitSALOAD(SALOAD sALOAD) { + this.processType2(sALOAD, this.stack().peek()); + if (this.stack().peek(1) != Type.NULL) { + if (!(this.stack().peek(1) instanceof ArrayType)) { + this.constraintViolated( + sALOAD, + "Stack next-to-top must be of type short[] but is '" + this.stack().peek(1) + "'."); + } + if (((ArrayType) this.stack().peek(1)).getBasicType() != Type.SHORT) { + this.constraintViolated( + sALOAD, + "Stack next-to-top must be of type short[] but is '" + this.stack().peek(1) + "'."); + } + } + } + + @Override + public void visitIF_ICMPGT(IF_ICMPGT f_ICMPGT) { + if (this.stack().peek() != Type.INT) { + this.constraintViolated( + f_ICMPGT, + "The value at the stack top is not of type 'int', but of type '" + + this.stack().peek() + + "'."); + } + if (this.stack().peek(1) != Type.INT) { + this.constraintViolated( + f_ICMPGT, + "The value at the stack next-to-top is not of type 'int', but of type '" + + this.stack().peek(1) + + "'."); + } + } + + @Override + public void visitDALOAD(DALOAD dALOAD) { + this.processType2(dALOAD, this.stack().peek()); + if (this.stack().peek(1) != Type.NULL) { + if (!(this.stack().peek(1) instanceof ArrayType)) { + this.constraintViolated( + dALOAD, + "Stack next-to-top must be of type double[] but is '" + this.stack().peek(1) + "'."); + } + if (((ArrayType) this.stack().peek(1)).getBasicType() != Type.DOUBLE) { + this.constraintViolated( + dALOAD, + "Stack next-to-top must be of type double[] but is '" + this.stack().peek(1) + "'."); + } + } + } + + @Override + public void visitL2F(L2F l2F) { + if (this.stack().peek() != Type.LONG) { + this.constraintViolated( + l2F, + "The value at the stack top is not of type 'long', but of type '" + + this.stack().peek() + + "'."); + } + } + + @Override + public void visitDDIV(DDIV dDIV) { + if (this.stack().peek() != Type.DOUBLE) { + this.constraintViolated( + dDIV, + "The value at the stack top is not of type 'double', but of type '" + + this.stack().peek() + + "'."); + } + if (this.stack().peek(1) != Type.DOUBLE) { + this.constraintViolated( + dDIV, + "The value at the stack next-to-top is not of type 'double', but of type '" + + this.stack().peek(1) + + "'."); + } + } + + @Override + public void visitPOP(POP pOP) { + if (this.stack().peek().getSize() != 1) { + this.constraintViolated( + pOP, + "Stack top size should be 1 but stack top is '" + + this.stack().peek() + + "' of size '" + + this.stack().peek().getSize() + + "'."); + } + } + + @Override + public void visitLSTORE(LSTORE lSTORE) {} + + @Override + public void visitF2D(F2D f2D) { + if (this.stack().peek() != Type.FLOAT) { + this.constraintViolated( + f2D, + "The value at the stack top is not of type 'float', but of type '" + + this.stack().peek() + + "'."); + } + } + + @Override + public void visitNEWARRAY(NEWARRAY nEWARRAY) { + if (this.stack().peek() != Type.INT) { + this.constraintViolated( + nEWARRAY, + "The value at the stack top is not of type 'int', but of type '" + + this.stack().peek() + + "'."); + } + } + + @Override + public void visitLAND(LAND lAND) { + if (this.stack().peek() != Type.LONG) { + this.constraintViolated( + lAND, + "The value at the stack top is not of type 'long', but of type '" + + this.stack().peek() + + "'."); + } + if (this.stack().peek(1) != Type.LONG) { + this.constraintViolated( + lAND, + "The value at the stack next-to-top is not of type 'long', but of type '" + + this.stack().peek(1) + + "'."); + } + } + + @Override + public void visitDLOAD(DLOAD dLOAD) {} + + @Override + public void visitStoreInstruction(StoreInstruction storeInstruction) { + if (this.stack().isEmpty()) { + this.constraintViolated(storeInstruction, "Cannot STORE: Stack to read from is empty."); + } + if (!(storeInstruction instanceof ASTORE)) { + if (this.stack().peek() != storeInstruction.getType(this.cpg)) { + this.constraintViolated( + storeInstruction, + "Stack top type and STOREing Instruction type mismatch: Stack top: '" + + this.stack().peek() + + "'; Instruction type: '" + + storeInstruction.getType(this.cpg) + + "'."); + return; + } + } else { + Type type; + if (!((type = this.stack().peek()) instanceof ReferenceType) + && !(type instanceof ReturnaddressType)) { + this.constraintViolated( + storeInstruction, + "Stack top type and STOREing Instruction type mismatch: Stack top: '" + + this.stack().peek() + + "'; Instruction expects a ReferenceType or a ReturnadressType."); + } + } + } + + @Override + public void visitARETURN(ARETURN aRETURN) { + if (!(this.stack().peek() instanceof ReferenceType)) { + this.constraintViolated( + aRETURN, + "The 'objectref' at the stack top is not of a ReferenceType but of type '" + + this.stack().peek() + + "'."); + } + ReferenceType referenceType = (ReferenceType) this.stack().peek(); + this.referenceTypeIsInitialized(aRETURN, referenceType); + } + + @Override + public void visitLSHR(LSHR lSHR) { + if (this.stack().peek() != Type.INT) { + this.constraintViolated( + lSHR, + "The value at the stack top is not of type 'int', but of type '" + + this.stack().peek() + + "'."); + } + if (this.stack().peek(1) != Type.LONG) { + this.constraintViolated( + lSHR, + "The value at the stack next-to-top is not of type 'long', but of type '" + + this.stack().peek(1) + + "'."); + } + } + + @Override + public void visitDASTORE(DASTORE dASTORE) { + if (this.stack().peek() != Type.DOUBLE) { + this.constraintViolated( + dASTORE, + "The value at the stack top is not of type 'double', but of type '" + + this.stack().peek() + + "'."); + } + this.processType2(dASTORE, this.stack().peek(1)); + if (this.stack().peek(2) != Type.NULL) { + if (!(this.stack().peek(2) instanceof ArrayType)) { + this.constraintViolated( + dASTORE, + "Stack next-to-next-to-top must be of type double[] but is '" + + this.stack().peek(2) + + "'."); + } + if (((ArrayType) this.stack().peek(2)).getBasicType() != Type.DOUBLE) { + this.constraintViolated( + dASTORE, + "Stack next-to-next-to-top must be of type double[] but is '" + + this.stack().peek(2) + + "'."); + } + } + } + + @Override + public void visitFALOAD(FALOAD fALOAD) { + this.processType2(fALOAD, this.stack().peek()); + if (this.stack().peek(1) != Type.NULL) { + if (!(this.stack().peek(1) instanceof ArrayType)) { + this.constraintViolated( + fALOAD, + "Stack next-to-top must be of type float[] but is '" + this.stack().peek(1) + "'."); + } + if (((ArrayType) this.stack().peek(1)).getBasicType() != Type.FLOAT) { + this.constraintViolated( + fALOAD, + "Stack next-to-top must be of type float[] but is '" + this.stack().peek(1) + "'."); + } + } + } + + @Override + public void visitIFLT(IFLT fLT) { + if (this.stack().peek() != Type.INT) { + this.constraintViolated( + fLT, + "The value at the stack top is not of type 'int', but of type '" + + this.stack().peek() + + "'."); + } + } + + @Override + public void visitLADD(LADD lADD) { + if (this.stack().peek() != Type.LONG) { + this.constraintViolated( + lADD, + "The value at the stack top is not of type 'long', but of type '" + + this.stack().peek() + + "'."); + } + if (this.stack().peek(1) != Type.LONG) { + this.constraintViolated( + lADD, + "The value at the stack next-to-top is not of type 'long', but of type '" + + this.stack().peek(1) + + "'."); + } + } + + @Override + public void visitI2C(I2C i2C) { + if (this.stack().peek() != Type.INT) { + this.constraintViolated( + i2C, + "The value at the stack top is not of type 'int', but of type '" + + this.stack().peek() + + "'."); + } + } + + @Override + public void visitFCMPG(FCMPG fCMPG) { + if (this.stack().peek() != Type.FLOAT) { + this.constraintViolated( + fCMPG, + "The value at the stack top is not of type 'float', but of type '" + + this.stack().peek() + + "'."); + } + if (this.stack().peek(1) != Type.FLOAT) { + this.constraintViolated( + fCMPG, + "The value at the stack next-to-top is not of type 'float', but of type '" + + this.stack().peek(1) + + "'."); + } + } + + @Override + public void visitLoadClass(LoadClass loadClass) { + ObjectType objectType; + VerificationResult verificationResult; + if ((objectType = loadClass.getLoadClassType(this.cpg)) != null + && (verificationResult = + VerifierFactory.getVerifier(objectType.getClassName()) + .createVerificationResult2()) + .getStatus() + != 1) { + this.constraintViolated( + (Instruction) loadClass, + "Class '" + + loadClass.getLoadClassType(this.cpg).getClassName() + + "' is referenced, but cannot be loaded and resolved: '" + + verificationResult + + "'."); + } + } + + @Override + public void visitFCMPL(FCMPL fCMPL) { + if (this.stack().peek() != Type.FLOAT) { + this.constraintViolated( + fCMPL, + "The value at the stack top is not of type 'float', but of type '" + + this.stack().peek() + + "'."); + } + if (this.stack().peek(1) != Type.FLOAT) { + this.constraintViolated( + fCMPL, + "The value at the stack next-to-top is not of type 'float', but of type '" + + this.stack().peek(1) + + "'."); + } + } + + @Override + public void visitTABLESWITCH(TABLESWITCH tABLESWITCH) { + this.processType2(tABLESWITCH, this.stack().peek()); + } + + @Override + public void visitDUP2(DUP2 dUP2) { + if (this.stack().peek().getSize() != 2) { + if (this.stack().peek(1).getSize() != 1) { + this.constraintViolated( + dUP2, + "If stack top's size is 1, then stack next-to-top's size must also be 1. But it is '" + + this.stack().peek(1) + + "' of size '" + + this.stack().peek(1).getSize() + + "'."); + } + } + } + + @Override + public void visitInvokeInstruction(InvokeInstruction invokeInstruction) {} + + @Override + public void visitI2D(I2D i2D) { + if (this.stack().peek() != Type.INT) { + this.constraintViolated( + i2D, + "The value at the stack top is not of type 'int', but of type '" + + this.stack().peek() + + "'."); + } + } + + @Override + public void visitMONITORENTER(MONITORENTER mONITORENTER) { + if (!(this.stack().peek() instanceof ReferenceType)) { + this.constraintViolated( + mONITORENTER, + "The stack top should be of a ReferenceType, but is '" + this.stack().peek() + "'."); + } + } + + @Override + public void visitIUSHR(IUSHR uSHR) { + if (this.stack().peek() != Type.INT) { + this.constraintViolated( + uSHR, + "The value at the stack top is not of type 'int', but of type '" + + this.stack().peek() + + "'."); + } + if (this.stack().peek(1) != Type.INT) { + this.constraintViolated( + uSHR, + "The value at the stack next-to-top is not of type 'int', but of type '" + + this.stack().peek(1) + + "'."); + } + } + + @Override + public void visitIRETURN(IRETURN rETURN) { + if (this.stack().peek() != Type.INT) { + this.constraintViolated( + rETURN, + "The value at the stack top is not of type 'int', but of type '" + + this.stack().peek() + + "'."); + } + } + + @Override + public void visitIXOR(IXOR xOR) { + if (this.stack().peek() != Type.INT) { + this.constraintViolated( + xOR, + "The value at the stack top is not of type 'int', but of type '" + + this.stack().peek() + + "'."); + } + if (this.stack().peek(1) != Type.INT) { + this.constraintViolated( + xOR, + "The value at the stack next-to-top is not of type 'int', but of type '" + + this.stack().peek(1) + + "'."); + } + } + + @Override + public void visitLNEG(LNEG lNEG) { + if (this.stack().peek() != Type.LONG) { + this.constraintViolated( + lNEG, + "The value at the stack top is not of type 'long', but of type '" + + this.stack().peek() + + "'."); + } + } + + @Override + public void visitFSTORE(FSTORE fSTORE) {} + + @Override + public void visitILOAD(ILOAD lOAD) {} + + @Override + public void visitFieldInstruction(FieldInstruction fieldInstruction) { + Constant constant; + if (!((constant = this.cpg.getConstant(fieldInstruction.getIndex())) + instanceof ConstantFieldref)) { + this.constraintViolated( + fieldInstruction, + "Index '" + + fieldInstruction.getIndex() + + "' should refer to a CONSTANT_Fieldref_info structure, but refers to '" + + constant + + "'."); + } + String text; + Type type; + VerificationResult verificationResult; + if ((type = fieldInstruction.getType(this.cpg)) instanceof ObjectType + && (verificationResult = + VerifierFactory.getVerifier(text = ((ObjectType) type).getClassName()) + .createVerificationResult2()) + .getStatus() + != 1) { + this.constraintViolated( + fieldInstruction, + "Class '" + + text + + "' is referenced, but cannot be loaded and resolved: '" + + verificationResult + + "'."); + } + } + + @Override + public void visitANEWARRAY(ANEWARRAY aNEWARRAY) { + if (!this.stack().peek().equals(Type.INT)) { + this.constraintViolated( + aNEWARRAY, + "The 'count' at the stack top is not of type '" + + Type.INT + + "' but of type '" + + this.stack().peek() + + "'."); + } + } + + @Override + public void visitCHECKCAST(CHECKCAST cHECKCAST) { + Type type; + if (!((type = this.stack().peek(0)) instanceof ReferenceType)) { + this.constraintViolated( + cHECKCAST, "The 'objectref' is not of a ReferenceType but of type " + type + "."); + } + Constant constant; + if (!((constant = this.cpg.getConstant(cHECKCAST.getIndex())) instanceof ConstantClass)) { + this.constraintViolated( + cHECKCAST, "The Constant at 'index' is not a ConstantClass, but '" + constant + "'."); + } + } + + @Override + public void visitLALOAD(LALOAD lALOAD) { + this.processType2(lALOAD, this.stack().peek()); + if (this.stack().peek(1) != Type.NULL) { + if (!(this.stack().peek(1) instanceof ArrayType)) { + this.constraintViolated( + lALOAD, + "Stack next-to-top must be of type long[] but is '" + this.stack().peek(1) + "'."); + } + if (((ArrayType) this.stack().peek(1)).getBasicType() != Type.LONG) { + this.constraintViolated( + lALOAD, + "Stack next-to-top must be of type long[] but is '" + this.stack().peek(1) + "'."); + } + } + } + + @Override + public void visitISUB(ISUB sUB) { + if (this.stack().peek() != Type.INT) { + this.constraintViolated( + sUB, + "The value at the stack top is not of type 'int', but of type '" + + this.stack().peek() + + "'."); + } + if (this.stack().peek(1) != Type.INT) { + this.constraintViolated( + sUB, + "The value at the stack next-to-top is not of type 'int', but of type '" + + this.stack().peek(1) + + "'."); + } + } + + @Override + public void visitFREM(FREM fREM) { + if (this.stack().peek() != Type.FLOAT) { + this.constraintViolated( + fREM, + "The value at the stack top is not of type 'float', but of type '" + + this.stack().peek() + + "'."); + } + if (this.stack().peek(1) != Type.FLOAT) { + this.constraintViolated( + fREM, + "The value at the stack next-to-top is not of type 'float', but of type '" + + this.stack().peek(1) + + "'."); + } + } + + @Override + public void visitSIPUSH(SIPUSH sIPUSH) {} + + public boolean arrayrefOfArrayType(Instruction instruction, Type type) { + if (!(type instanceof ArrayType) && !type.equals(Type.NULL)) { + this.constraintViolated( + instruction, "The 'arrayref' does not refer to an array but is of type " + type + "."); + } + return type instanceof ArrayType; + } + + @Override + public void visitDCMPL(DCMPL dCMPL) { + if (this.stack().peek() != Type.DOUBLE) { + this.constraintViolated( + dCMPL, + "The value at the stack top is not of type 'double', but of type '" + + this.stack().peek() + + "'."); + } + if (this.stack().peek(1) != Type.DOUBLE) { + this.constraintViolated( + dCMPL, + "The value at the stack next-to-top is not of type 'double', but of type '" + + this.stack().peek(1) + + "'."); + } + } + + @Override + public void visitBIPUSH(BIPUSH bIPUSH) {} + + @Override + public void visitIADD(IADD aDD) { + if (this.stack().peek() != Type.INT) { + this.constraintViolated( + aDD, + "The value at the stack top is not of type 'int', but of type '" + + this.stack().peek() + + "'."); + } + if (this.stack().peek(1) != Type.INT) { + this.constraintViolated( + aDD, + "The value at the stack next-to-top is not of type 'int', but of type '" + + this.stack().peek(1) + + "'."); + } + } + + @Override + public void visitACONST_NULL(ACONST_NULL aCONST_NULL) {} + + @Override + public void visitLDIV(LDIV lDIV) { + if (this.stack().peek() != Type.LONG) { + this.constraintViolated( + lDIV, + "The value at the stack top is not of type 'long', but of type '" + + this.stack().peek() + + "'."); + } + if (this.stack().peek(1) != Type.LONG) { + this.constraintViolated( + lDIV, + "The value at the stack next-to-top is not of type 'long', but of type '" + + this.stack().peek(1) + + "'."); + } + } + + @Override + public void visitFRETURN(FRETURN fRETURN) { + if (this.stack().peek() != Type.FLOAT) { + this.constraintViolated( + fRETURN, + "The value at the stack top is not of type 'float', but of type '" + + this.stack().peek() + + "'."); + } + } + + public void setConstantPoolGen(ConstantPoolGen constantPoolGen) { + this.cpg = constantPoolGen; + } + + @Override + public void visitIINC(IINC iNC) { + if (this.locals().getLocals() + <= (iNC.getType(this.cpg).getSize() == 1 ? iNC.getIndex() : iNC.getIndex() + 1)) { + this.constraintViolated( + iNC, "The 'index' is not a valid index into the local variable array."); + } + this.processType2(iNC, this.locals().get(iNC.getIndex())); + } + + @Override + public void visitStackConsumer(StackConsumer stackConsumer) { + this._visitStackAccessor((Instruction) stackConsumer); + } + + public InstConstraintVisitor() { + this.cpg = null; + this.mg = null; + } + + @Override + public void visitIAND(IAND aND) { + if (this.stack().peek() != Type.INT) { + this.constraintViolated( + aND, + "The value at the stack top is not of type 'int', but of type '" + + this.stack().peek() + + "'."); + } + if (this.stack().peek(1) != Type.INT) { + this.constraintViolated( + aND, + "The value at the stack next-to-top is not of type 'int', but of type '" + + this.stack().peek(1) + + "'."); + } + } + + @Override + public void visitALOAD(ALOAD aLOAD) {} + + public void _visitStackAccessor(Instruction instruction) { + int value; + if ((value = instruction.consumeStack(this.cpg)) > this.stack().slotsUsed()) { + this.constraintViolated( + instruction, + "Cannot consume " + + value + + " stack slots: only " + + this.stack().slotsUsed() + + " slot(s) left on stack!\nStack:\n" + + this.stack()); + } + int value2; + if ((value2 = instruction.produceStack(this.cpg) - instruction.consumeStack(this.cpg)) + + this.stack().slotsUsed() + > this.stack().maxStack()) { + this.constraintViolated( + instruction, + "Cannot produce " + + value2 + + " stack slots: only " + + (this.stack().maxStack() - this.stack().slotsUsed()) + + " free stack slot(s) left.\nStack:\n" + + this.stack()); + } + } + + @Override + public void visitMULTIANEWARRAY(MULTIANEWARRAY mULTIANEWARRAY) { + short dimensions = mULTIANEWARRAY.getDimensions(); + int value; + for (int value2 = value = 0; value2 < dimensions; value2 = ++value) { + if (this.stack().peek(value) != Type.INT) { + this.constraintViolated( + mULTIANEWARRAY, + "The '" + dimensions + "' upper stack types should be 'int' but aren't."); + } + } + } + + @Override + public void visitLSHL(LSHL lSHL) { + if (this.stack().peek() != Type.INT) { + this.constraintViolated( + lSHL, + "The value at the stack top is not of type 'int', but of type '" + + this.stack().peek() + + "'."); + } + if (this.stack().peek(1) != Type.LONG) { + this.constraintViolated( + lSHL, + "The value at the stack next-to-top is not of type 'long', but of type '" + + this.stack().peek(1) + + "'."); + } + } + + @Override + public void visitISTORE(ISTORE sTORE) {} + + @Override + public void visitLDC(LDC lDC) { + Constant constant; + if (!((constant = this.cpg.getConstant(lDC.getIndex())) instanceof ConstantInteger) + && !(constant instanceof ConstantFloat) + && !(constant instanceof ConstantString)) { + this.constraintViolated( + lDC, + "Referenced constant should be a CONSTANT_Integer, a CONSTANT_Float or a CONSTANT_String," + + " but is '" + + constant + + "'."); + } + } + + @Override + public void visitBALOAD(BALOAD bALOAD) { + Type type = this.stack().peek(1); + Type type2 = this.stack().peek(0); + this.processType2(bALOAD, type2); + if (this.arrayrefOfArrayType(bALOAD, type) + && !((ArrayType) type).getElementType().equals(Type.BOOLEAN) + && !((ArrayType) type).getElementType().equals(Type.BYTE)) { + this.constraintViolated( + bALOAD, + "The 'arrayref' does not refer to an array with elements of a Type.BYTE or Type.BOOLEAN" + + " but to an array of '" + + ((ArrayType) type).getElementType() + + "'."); + } + } + + public void processType(Instruction instruction, Type type) { + if (!type.equals(Type.INT)) { + this.constraintViolated( + instruction, "The 'value' is not of type int but of type " + type + "."); + } + } + + @Override + public void visitSWAP(SWAP sWAP) { + if (this.stack().peek().getSize() != 1) { + this.constraintViolated( + sWAP, + "The value at the stack top is not of size '1', but of size '" + + this.stack().peek().getSize() + + "'."); + } + if (this.stack().peek(1).getSize() != 1) { + this.constraintViolated( + sWAP, + "The value at the stack next-to-top is not of size '1', but of size '" + + this.stack().peek(1).getSize() + + "'."); + } + } + + @Override + public void visitICONST(ICONST cONST) {} + + @Override + public void visitGETFIELD(GETFIELD gETFIELD) { + Field field; + Field field2; + try { + Type type; + if (!((type = this.stack().peek()) instanceof ObjectType) && type != Type.NULL) { + this.constraintViolated( + gETFIELD, + "Stack top should be an object reference that's not an array reference, but is '" + + type + + "'."); + } + String fieldName = gETFIELD.getFieldName(this.cpg); + JavaClass javaClass; + Field[] fields = + (javaClass = Repository.lookupClass(gETFIELD.createObjectType(this.cpg).getClassName())) + .getFields(); + Field field3 = null; + int value; + int value2 = value = 0; + while (true) { + if (value2 >= fields.length) { + field2 = field3; + break; + } + if (fields[value].getText().equals(fieldName)) { + Type type2 = Type.getType(fields[value].getText2()); + Type type3 = gETFIELD.getType(this.cpg); + if (type2.equals(type3)) { + field2 = field3 = fields[value]; + break; + } + } + value2 = ++value; + } + if (field2 == null) { + JavaClass[] javaClasss = javaClass.createJavaClasss(); + label76: + { + int value3; + label75: + for (int value4 = value3 = 0; value4 < javaClasss.length; value4 = ++value3) { + Field[] fields2 = javaClasss[value3].getFields(); + int value5; + for (int value6 = value5 = 0; value6 < fields2.length; value6 = ++value5) { + if (fields2[value5].getText().equals(fieldName)) { + Type type4 = Type.getType(fields2[value5].getText2()); + Type type5 = gETFIELD.getType(this.cpg); + if (type4.equals(type5)) { + if (((field3 = fields2[value5]).getAccess_flags2() & 5) == 0) { + field = field3 = null; + break label76; + } + break label75; + } + } + } + } + field = field3; + } + if (field == null) { + throw new AssertionViolatedException(("Field '" + fieldName + "' not found?!?")); + } + } + if (field3.isEnabled13()) { + ObjectType objectType = gETFIELD.createObjectType(this.cpg); + ObjectType objectType2 = new ObjectType(this.mg.getClass_name()); + if (objectType.equals(objectType2) || objectType2.matchesObjectType(objectType)) { + Type type6; + if ((type6 = this.stack().peek()) == Type.NULL) { + return; + } + if (!(type6 instanceof ObjectType)) { + this.constraintViolated( + gETFIELD, + "The 'objectref' must refer to an object that's not an array. Found instead: '" + + type6 + + "'."); + } + ObjectType objectType3; + if (!(objectType3 = (ObjectType) type6).equals(objectType2) + && !objectType3.matchesObjectType(objectType2)) {} + } + } + if (field3.isEnabled11()) { + this.constraintViolated( + gETFIELD, "Referenced field '" + field3 + "' is static which it shouldn't be."); + } + } catch (ClassNotFoundException classNotFoundException) { + throw new AssertionViolatedException(("Missing class: " + classNotFoundException.toString())); + } + } + + @Override + public void visitIFLE(IFLE fLE) { + if (this.stack().peek() != Type.INT) { + this.constraintViolated( + fLE, + "The value at the stack top is not of type 'int', but of type '" + + this.stack().peek() + + "'."); + } + } + + @Override + public void visitL2D(L2D l2D) { + if (this.stack().peek() != Type.LONG) { + this.constraintViolated( + l2D, + "The value at the stack top is not of type 'long', but of type '" + + this.stack().peek() + + "'."); + } + } + + @Override + public void visitLOOKUPSWITCH(LOOKUPSWITCH lOOKUPSWITCH) { + if (this.stack().peek() != Type.INT) { + this.constraintViolated( + lOOKUPSWITCH, + "The value at the stack top is not of type 'int', but of type '" + + this.stack().peek() + + "'."); + } + } + + @Override + public void visitMONITOREXIT(MONITOREXIT mONITOREXIT) { + if (!(this.stack().peek() instanceof ReferenceType)) { + this.constraintViolated( + mONITOREXIT, + "The stack top should be of a ReferenceType, but is '" + this.stack().peek() + "'."); + } + } + + @Override + public void visitIF_ICMPEQ(IF_ICMPEQ f_ICMPEQ) { + if (this.stack().peek() != Type.INT) { + this.constraintViolated( + f_ICMPEQ, + "The value at the stack top is not of type 'int', but of type '" + + this.stack().peek() + + "'."); + } + if (this.stack().peek(1) != Type.INT) { + this.constraintViolated( + f_ICMPEQ, + "The value at the stack next-to-top is not of type 'int', but of type '" + + this.stack().peek(1) + + "'."); + } + } + + @Override + public void visitIMUL(IMUL mUL) { + if (this.stack().peek() != Type.INT) { + this.constraintViolated( + mUL, + "The value at the stack top is not of type 'int', but of type '" + + this.stack().peek() + + "'."); + } + if (this.stack().peek(1) != Type.INT) { + this.constraintViolated( + mUL, + "The value at the stack next-to-top is not of type 'int', but of type '" + + this.stack().peek(1) + + "'."); + } + } + + public LocalVariables locals() { + return this.frame.getLocals(); + } + + @Override + public void visitDUP_X2(DUP_X2 dUP_X2) { + if (this.stack().peek().getSize() != 1) { + this.constraintViolated( + dUP_X2, + "Stack top type must be of size 1, but is '" + + this.stack().peek() + + "' of size '" + + this.stack().peek().getSize() + + "'."); + } + if (this.stack().peek(1).getSize() != 2) { + if (this.stack().peek(2).getSize() != 1) { + this.constraintViolated( + dUP_X2, + "If stack top's size is 1 and stack next-to-top's size is 1, stack" + + " next-to-next-to-top's size must also be 1, but is: '" + + this.stack().peek(2) + + "' of size '" + + this.stack().peek(2).getSize() + + "'."); + } + } + } + + @Override + public void visitIF_ICMPGE(IF_ICMPGE f_ICMPGE) { + if (this.stack().peek() != Type.INT) { + this.constraintViolated( + f_ICMPGE, + "The value at the stack top is not of type 'int', but of type '" + + this.stack().peek() + + "'."); + } + if (this.stack().peek(1) != Type.INT) { + this.constraintViolated( + f_ICMPGE, + "The value at the stack next-to-top is not of type 'int', but of type '" + + this.stack().peek(1) + + "'."); + } + } + + @Override + public void visitIMPDEP1(IMPDEP1 mPDEP1) { + throw new AssertionViolatedException( + "In this JustIce verification pass there should not occur an illegal instruction such as" + + " IMPDEP1."); + } + + @Override + public void visitBREAKPOINT(BREAKPOINT bREAKPOINT) { + throw new AssertionViolatedException( + "In this JustIce verification pass there should not occur an illegal instruction such as" + + " BREAKPOINT."); + } + + @Override + public void visitAASTORE(AASTORE aASTORE) { + try { + Type type = this.stack().peek(2); + Type type2 = this.stack().peek(1); + Type type3 = this.stack().peek(0); + this.processType2(aASTORE, type2); + if (!(type3 instanceof ReferenceType)) { + this.constraintViolated( + aASTORE, "The 'value' is not of a ReferenceType but of type " + type3 + "."); + } + if (this.arrayrefOfArrayType(aASTORE, type)) { + if (!(((ArrayType) type).getElementType() instanceof ReferenceType)) { + this.constraintViolated( + aASTORE, + "The 'arrayref' does not refer to an array with elements of a ReferenceType but to an" + + " array of " + + ((ArrayType) type).getElementType() + + "."); + } + if (!((ReferenceType) type3) + .matchesType2((ReferenceType) ((ArrayType) type).getElementType())) { + this.constraintViolated( + aASTORE, + "The type of 'value' ('" + + type3 + + "') is not assignment compatible to the components of the array 'arrayref'" + + " refers to. ('" + + ((ArrayType) type).getElementType() + + "')"); + return; + } + } + } catch (ClassNotFoundException classNotFoundException) { + throw new AssertionViolatedException(("Missing class: " + classNotFoundException.toString())); + } + } + + @Override + public void visitINVOKEINTERFACE(INVOKEINTERFACE nVOKEINTERFACE) { + int value; + if ((value = nVOKEINTERFACE.getCount()) == 0) { + this.constraintViolated(nVOKEINTERFACE, "The 'count' argument must not be 0."); + } + Type type; + VerificationResult verificationResult; + String text; + if ((type = nVOKEINTERFACE.getType(this.cpg)) instanceof ObjectType + && (verificationResult = + VerifierFactory.getVerifier(text = ((ObjectType) type).getClassName()) + .createVerificationResult2()) + .getStatus() + != 1) { + this.constraintViolated( + nVOKEINTERFACE, + "Class '" + + text + + "' is referenced, but cannot be loaded and resolved: '" + + verificationResult + + "'."); + } + int value2; + int value3; + Type[] types; + for (int value4 = + value2 = (value3 = (types = nVOKEINTERFACE.getArgumentTypes(this.cpg)).length) - 1; + value4 >= 0; + value4 = --value2) { + Type type2 = this.stack().peek(value3 - 1 - value2); + Type type3; + if ((type3 = types[value2]) == Type.BOOLEAN + || type3 == Type.BYTE + || type3 == Type.CHAR + || type3 == Type.SHORT) { + type3 = Type.INT; + } + if (!type2.equals(type3)) { + if (type2 instanceof ReferenceType && type3 instanceof ReferenceType) { + ReferenceType referenceType = (ReferenceType) type2; + this.referenceTypeIsInitialized(nVOKEINTERFACE, referenceType); + } else { + this.constraintViolated( + nVOKEINTERFACE, + "Expecting a '" + type3 + "' but found a '" + type2 + "' on the stack."); + } + } + } + Type type4; + if ((type4 = this.stack().peek(value3)) != Type.NULL) { + if (!(type4 instanceof ReferenceType)) { + this.constraintViolated( + nVOKEINTERFACE, + "Expecting a reference type as 'objectref' on the stack, not a '" + type4 + "'."); + } + this.referenceTypeIsInitialized(nVOKEINTERFACE, (ReferenceType) type4); + if (!(type4 instanceof ObjectType)) { + if (!(type4 instanceof ArrayType)) { + this.constraintViolated( + nVOKEINTERFACE, + "Expecting an ObjectType as 'objectref' on the stack, not a '" + type4 + "'."); + } + } + int value5 = 1; + int value6; + for (int value7 = value6 = 0; value7 < value3; value7 = value6) { + Type type5 = types[value6]; + int value8 = value5; + value6++; + value5 = value8 + type5.getSize(); + } + if (value != value5) { + this.constraintViolated( + nVOKEINTERFACE, + "The 'count' argument should probably read '" + value5 + "' but is '" + value + "'."); + } + } + } + + @Override + public void visitLMUL(LMUL lMUL) { + if (this.stack().peek() != Type.LONG) { + this.constraintViolated( + lMUL, + "The value at the stack top is not of type 'long', but of type '" + + this.stack().peek() + + "'."); + } + if (this.stack().peek(1) != Type.LONG) { + this.constraintViolated( + lMUL, + "The value at the stack next-to-top is not of type 'long', but of type '" + + this.stack().peek(1) + + "'."); + } + } + + @Override + public void visitDSUB(DSUB dSUB) { + if (this.stack().peek() != Type.DOUBLE) { + this.constraintViolated( + dSUB, + "The value at the stack top is not of type 'double', but of type '" + + this.stack().peek() + + "'."); + } + if (this.stack().peek(1) != Type.DOUBLE) { + this.constraintViolated( + dSUB, + "The value at the stack next-to-top is not of type 'double', but of type '" + + this.stack().peek(1) + + "'."); + } + } + + @Override + public void visitINVOKESPECIAL(INVOKESPECIAL nVOKESPECIAL) { + Type type; + try { + if (nVOKESPECIAL.getText4(this.cpg).equals("") + && !(this.stack().peek(nVOKESPECIAL.getArgumentTypes(this.cpg).length) + instanceof UninitializedObjectType)) { + this.constraintViolated( + nVOKESPECIAL, + "Possibly initializing object twice. A valid instruction sequence must not have an" + + " uninitialized object on the operand stack or in a local variable during a" + + " backwards branch, or in a local variable in code protected by an exception" + + " handler. Please see The Java Virtual Machine Specification, Second Edition," + + " 4.9.4 (pages 147 and 148) for details."); + } + String text; + VerificationResult verificationResult; + Type type2; + if ((type2 = nVOKESPECIAL.getType(this.cpg)) instanceof ObjectType + && (verificationResult = + VerifierFactory.getVerifier(text = ((ObjectType) type2).getClassName()) + .createVerificationResult2()) + .getStatus() + != 1) { + this.constraintViolated( + nVOKESPECIAL, + "Class '" + + text + + "' is referenced, but cannot be loaded and resolved: '" + + verificationResult + + "'."); + } + int value; + int value2; + Type[] types; + for (int value3 = + value2 = (value = (types = nVOKESPECIAL.getArgumentTypes(this.cpg)).length) - 1; + value3 >= 0; + value3 = --value2) { + Type type3 = this.stack().peek(value - 1 - value2); + Type type4; + if ((type4 = types[value2]) == Type.BOOLEAN + || type4 == Type.BYTE + || type4 == Type.CHAR + || type4 == Type.SHORT) { + type4 = Type.INT; + } + if (!type3.equals(type4)) { + if (type3 instanceof ReferenceType && type4 instanceof ReferenceType) { + ReferenceType referenceType = (ReferenceType) type3; + ReferenceType referenceType2 = (ReferenceType) type4; + if (!referenceType.matchesType2(referenceType2)) { + this.constraintViolated( + nVOKESPECIAL, + "Expecting a '" + + type4 + + "' but found a '" + + type3 + + "' on the stack (which is not assignment compatible)."); + } + this.referenceTypeIsInitialized(nVOKESPECIAL, referenceType); + } else { + this.constraintViolated( + nVOKESPECIAL, + "Expecting a '" + type4 + "' but found a '" + type3 + "' on the stack."); + } + } + } + Type type5; + if ((type5 = this.stack().peek(value)) != Type.NULL) { + if (!(type5 instanceof ReferenceType)) { + this.constraintViolated( + nVOKESPECIAL, + "Expecting a reference type as 'objectref' on the stack, not a '" + type5 + "'."); + } + String text2; + INVOKESPECIAL nVOKESPECIAL2; + if (!nVOKESPECIAL.getText4(this.cpg).equals("")) { + label64: + { + this.referenceTypeIsInitialized(nVOKESPECIAL, (ReferenceType) type5); + if (!(type5 instanceof ObjectType)) { + if (!(type5 instanceof ArrayType)) { + type = type5; + this.constraintViolated( + nVOKESPECIAL, + "Expecting an ObjectType as 'objectref' on the stack, not a '" + type5 + "'."); + break label64; + } + type5 = GENERIC_ARRAY; + } + type = type5; + } + text2 = ((ObjectType) type).getClassName(); + nVOKESPECIAL2 = nVOKESPECIAL; + } else { + if (!(type5 instanceof UninitializedObjectType)) { + this.constraintViolated( + nVOKESPECIAL, + "Expecting an UninitializedObjectType as 'objectref' on the stack, not a '" + + type5 + + "'. Otherwise, you couldn't invoke a method since an array has no methods" + + " (not to speak of a return address)."); + } + text2 = ((UninitializedObjectType) type5).getInitialized().getClassName(); + nVOKESPECIAL2 = nVOKESPECIAL; + } + String text22 = nVOKESPECIAL2.getText2(this.cpg); + if (!Repository.matchesText(text2, text22)) { + this.constraintViolated( + nVOKESPECIAL, + "The 'objref' item '" + type5 + "' does not implement '" + text22 + "' as expected."); + } + } + } catch (ClassNotFoundException classNotFoundException) { + throw new AssertionViolatedException(("Missing class: " + classNotFoundException.toString())); + } + } + + @Override + public void visitFLOAD(FLOAD fLOAD) {} + + @Override + public void visitPUTFIELD(PUTFIELD pUTFIELD) { + Field field; + try { + Type type; + if (!((type = this.stack().peek(1)) instanceof ObjectType) && type != Type.NULL) { + this.constraintViolated( + pUTFIELD, + "Stack next-to-top should be an object reference that's not an array reference, but is" + + " '" + + type + + "'."); + } + String fieldName = pUTFIELD.getFieldName(this.cpg); + Field[] fields = + Repository.lookupClass(pUTFIELD.createObjectType(this.cpg).getClassName()).getFields(); + Field field2 = null; + int value; + int value2 = value = 0; + while (true) { + if (value2 >= fields.length) { + field = field2; + break; + } + if (fields[value].getText().equals(fieldName)) { + Type type2 = Type.getType(fields[value].getText2()); + Type type3 = pUTFIELD.getType(this.cpg); + if (type2.equals(type3)) { + field = field2 = fields[value]; + break; + } + } + value2 = ++value; + } + if (field == null) { + throw new AssertionViolatedException("Field not found?!?"); + } + Type type4 = this.stack().peek(); + Type type5; + Type type6 = type5 = Type.getType(field2.getText2()); + if (type6 == Type.BOOLEAN + || type6 == Type.BYTE + || type6 == Type.CHAR + || type6 == Type.SHORT) { + type6 = Type.INT; + } + if (type5 instanceof ReferenceType) { + ReferenceType referenceType; + if (type4 instanceof ReferenceType) { + ReferenceType referenceType2 = (ReferenceType) type4; + referenceType = referenceType2; + this.referenceTypeIsInitialized(pUTFIELD, referenceType2); + } else { + this.constraintViolated( + pUTFIELD, + "The stack top type '" + type4 + "' is not of a reference type as expected."); + referenceType = (ReferenceType) (Object) null; + } + if (!referenceType.matchesType2(type6)) { + this.constraintViolated( + pUTFIELD, + "The stack top type '" + + type4 + + "' is not assignment compatible with '" + + type6 + + "'."); + } + } else if (type6 != type4) { + this.constraintViolated( + pUTFIELD, + "The stack top type '" + type4 + "' is not of type '" + type6 + "' as expected."); + } + if (field2.isEnabled13()) { + ObjectType objectType = pUTFIELD.createObjectType(this.cpg); + ObjectType objectType2 = new ObjectType(this.mg.getClass_name()); + if (objectType.equals(objectType2) || objectType2.matchesObjectType(objectType)) { + Type type7; + if ((type7 = this.stack().peek(1)) == Type.NULL) { + return; + } + if (!(type7 instanceof ObjectType)) { + this.constraintViolated( + pUTFIELD, + "The 'objectref' must refer to an object that's not an array. Found instead: '" + + type7 + + "'."); + } + ObjectType objectType3; + if (!(objectType3 = (ObjectType) type7).equals(objectType2) + && !objectType3.matchesObjectType(objectType2)) { + this.constraintViolated( + pUTFIELD, + "The referenced field has the ACC_PROTECTED modifier, and it's a member of the" + + " current class or a superclass of the current class. However, the referenced" + + " object type '" + + this.stack().peek() + + "' is not the current class or a subclass of the current class."); + } + } + } + if (field2.isEnabled11()) { + this.constraintViolated( + pUTFIELD, "Referenced field '" + field2 + "' is static which it shouldn't be."); + } + } catch (ClassNotFoundException classNotFoundException) { + throw new AssertionViolatedException(("Missing class: " + classNotFoundException.toString())); + } + } + + @Override + public void visitCASTORE(CASTORE cASTORE) { + Type type = this.stack().peek(2); + Type type2 = this.stack().peek(1); + Type type3 = this.stack().peek(0); + this.processType2(cASTORE, type2); + this.processType(cASTORE, type3); + if (this.arrayrefOfArrayType(cASTORE, type) + && !((ArrayType) type).getElementType().equals(Type.CHAR)) { + this.constraintViolated( + cASTORE, + "The 'arrayref' does not refer to an array with elements of type char but to an array of" + + " type " + + ((ArrayType) type).getElementType() + + "."); + } + } + + @Override + public void visitLUSHR(LUSHR lUSHR) { + if (this.stack().peek() != Type.INT) { + this.constraintViolated( + lUSHR, + "The value at the stack top is not of type 'int', but of type '" + + this.stack().peek() + + "'."); + } + if (this.stack().peek(1) != Type.LONG) { + this.constraintViolated( + lUSHR, + "The value at the stack next-to-top is not of type 'long', but of type '" + + this.stack().peek(1) + + "'."); + } + } + + @Override + public void visitF2L(F2L f2L) { + if (this.stack().peek() != Type.FLOAT) { + this.constraintViolated( + f2L, + "The value at the stack top is not of type 'float', but of type '" + + this.stack().peek() + + "'."); + } + } + + @Override + public void visitD2F(D2F d2F) { + if (this.stack().peek() != Type.DOUBLE) { + this.constraintViolated( + d2F, + "The value at the stack top is not of type 'double', but of type '" + + this.stack().peek() + + "'."); + } + } + + @Override + public void visitIF_ACMPNE(IF_ACMPNE f_ACMPNE) { + if (!(this.stack().peek() instanceof ReferenceType)) { + this.constraintViolated( + f_ACMPNE, + "The value at the stack top is not of a ReferenceType, but of type '" + + this.stack().peek() + + "'."); + } + if (!(this.stack().peek(1) instanceof ReferenceType)) { + this.constraintViolated( + f_ACMPNE, + "The value at the stack next-to-top is not of a ReferenceType, but of type '" + + this.stack().peek(1) + + "'."); + } + } + + @Override + public void visitF2I(F2I f2I) { + if (this.stack().peek() != Type.FLOAT) { + this.constraintViolated( + f2I, + "The value at the stack top is not of type 'float', but of type '" + + this.stack().peek() + + "'."); + } + } + + @Override + public void visitDADD(DADD dADD) { + if (this.stack().peek() != Type.DOUBLE) { + this.constraintViolated( + dADD, + "The value at the stack top is not of type 'double', but of type '" + + this.stack().peek() + + "'."); + } + if (this.stack().peek(1) != Type.DOUBLE) { + this.constraintViolated( + dADD, + "The value at the stack next-to-top is not of type 'double', but of type '" + + this.stack().peek(1) + + "'."); + } + } + + @Override + public void visitIFNULL(IFNULL fNULL) { + if (!(this.stack().peek() instanceof ReferenceType)) { + this.constraintViolated( + fNULL, + "The value at the stack top is not of a ReferenceType, but of type '" + + this.stack().peek() + + "'."); + } + this.referenceTypeIsInitialized(fNULL, (ReferenceType) this.stack().peek()); + } + + @Override + public void visitIFNONNULL(IFNONNULL fNONNULL) { + if (!(this.stack().peek() instanceof ReferenceType)) { + this.constraintViolated( + fNONNULL, + "The value at the stack top is not of a ReferenceType, but of type '" + + this.stack().peek() + + "'."); + } + this.referenceTypeIsInitialized(fNONNULL, (ReferenceType) this.stack().peek()); + } + + @Override + public void visitNEW(NEW nEW) { + Type type; + if (!((type = nEW.getType(this.cpg)) instanceof ReferenceType)) { + throw new AssertionViolatedException("NEW.getType() returning a non-reference type?!"); + } + if (!(type instanceof ObjectType)) { + this.constraintViolated( + nEW, "Expecting a class type (ObjectType) to work on. Found: '" + type + "'."); + } + ObjectType objectType; + if (!(objectType = (ObjectType) type).isClass_name2()) { + this.constraintViolated( + nEW, "Expecting a class type (ObjectType) to work on. Found: '" + objectType + "'."); + } + } + + @Override + public void visitFADD(FADD fADD) { + if (this.stack().peek() != Type.FLOAT) { + this.constraintViolated( + fADD, + "The value at the stack top is not of type 'float', but of type '" + + this.stack().peek() + + "'."); + } + if (this.stack().peek(1) != Type.FLOAT) { + this.constraintViolated( + fADD, + "The value at the stack next-to-top is not of type 'float', but of type '" + + this.stack().peek(1) + + "'."); + } + } + + @Override + public void visitIF_ICMPLE(IF_ICMPLE f_ICMPLE) { + if (this.stack().peek() != Type.INT) { + this.constraintViolated( + f_ICMPLE, + "The value at the stack top is not of type 'int', but of type '" + + this.stack().peek() + + "'."); + } + if (this.stack().peek(1) != Type.INT) { + this.constraintViolated( + f_ICMPLE, + "The value at the stack next-to-top is not of type 'int', but of type '" + + this.stack().peek(1) + + "'."); + } + } + + @Override + public void visitJSR_W(JSR_W jSR_W) {} + + @Override + public void visitCPInstruction(CPInstruction cPInstruction) { + int value; + if ((value = cPInstruction.getIndex()) < 0 || value >= this.cpg.getSize()) { + throw new AssertionViolatedException( + ("Huh?! Constant pool index of instruction '" + + cPInstruction + + "' illegal? Pass 3a should have checked this!")); + } + } + + @Override + public void visitLOR(LOR lOR) { + if (this.stack().peek() != Type.LONG) { + this.constraintViolated( + lOR, + "The value at the stack top is not of type 'long', but of type '" + + this.stack().peek() + + "'."); + } + if (this.stack().peek(1) != Type.LONG) { + this.constraintViolated( + lOR, + "The value at the stack next-to-top is not of type 'long', but of type '" + + this.stack().peek(1) + + "'."); + } + } + + @Override + public void visitLSUB(LSUB lSUB) { + if (this.stack().peek() != Type.LONG) { + this.constraintViolated( + lSUB, + "The value at the stack top is not of type 'long', but of type '" + + this.stack().peek() + + "'."); + } + if (this.stack().peek(1) != Type.LONG) { + this.constraintViolated( + lSUB, + "The value at the stack next-to-top is not of type 'long', but of type '" + + this.stack().peek(1) + + "'."); + } + } + + @Override + public void visitFDIV(FDIV fDIV) { + if (this.stack().peek() != Type.FLOAT) { + this.constraintViolated( + fDIV, + "The value at the stack top is not of type 'float', but of type '" + + this.stack().peek() + + "'."); + } + if (this.stack().peek(1) != Type.FLOAT) { + this.constraintViolated( + fDIV, + "The value at the stack next-to-top is not of type 'float', but of type '" + + this.stack().peek(1) + + "'."); + } + } + + @Override + public void visitDUP2_X2(DUP2_X2 dUP2_X2) { + InstConstraintVisitor instConstraintVisitor; + if (this.stack().peek(0).getSize() == 2) { + if (this.stack().peek(1).getSize() == 2) { + return; + } + if (this.stack().peek(2).getSize() == 1) { + return; + } + StringBuilder stringBuilder = + new StringBuilder() + .append( + "If stack top's size is 2 and stack-next-to-top's size is 1, then stack" + + " next-to-next-to-top's size must also be 1. But it is '"); + instConstraintVisitor = this; + this.constraintViolated( + dUP2_X2, + stringBuilder + .append(this.stack().peek(2)) + .append("' of size '") + .append(this.stack().peek(2).getSize()) + .append("'.") + .toString()); + } else { + if (this.stack().peek(1).getSize() == 1) { + if (this.stack().peek(2).getSize() == 2) { + return; + } + if (this.stack().peek(3).getSize() == 1) { + return; + } + } + instConstraintVisitor = this; + } + instConstraintVisitor.constraintViolated( + dUP2_X2, + "The operand sizes on the stack do not match any of the four forms of usage of this" + + " instruction."); + } + + @Override + public void visitLRETURN(LRETURN lRETURN) { + if (this.stack().peek() != Type.LONG) { + this.constraintViolated( + lRETURN, + "The value at the stack top is not of type 'long', but of type '" + + this.stack().peek() + + "'."); + } + } + + @Override + public void visitFASTORE(FASTORE fASTORE) { + if (this.stack().peek() != Type.FLOAT) { + this.constraintViolated( + fASTORE, + "The value at the stack top is not of type 'float', but of type '" + + this.stack().peek() + + "'."); + } + this.processType2(fASTORE, this.stack().peek(1)); + if (this.stack().peek(2) != Type.NULL) { + if (!(this.stack().peek(2) instanceof ArrayType)) { + this.constraintViolated( + fASTORE, + "Stack next-to-next-to-top must be of type float[] but is '" + + this.stack().peek(2) + + "'."); + } + if (((ArrayType) this.stack().peek(2)).getBasicType() != Type.FLOAT) { + this.constraintViolated( + fASTORE, + "Stack next-to-next-to-top must be of type float[] but is '" + + this.stack().peek(2) + + "'."); + } + } + } + + @Override + public void visitStackInstruction(StackInstruction stackInstruction) { + this._visitStackAccessor(stackInstruction); + } + + @Override + public void visitIDIV(IDIV dIV) { + if (this.stack().peek() != Type.INT) { + this.constraintViolated( + dIV, + "The value at the stack top is not of type 'int', but of type '" + + this.stack().peek() + + "'."); + } + if (this.stack().peek(1) != Type.INT) { + this.constraintViolated( + dIV, + "The value at the stack next-to-top is not of type 'int', but of type '" + + this.stack().peek(1) + + "'."); + } + } + + @Override + public void visitDMUL(DMUL dMUL) { + if (this.stack().peek() != Type.DOUBLE) { + this.constraintViolated( + dMUL, + "The value at the stack top is not of type 'double', but of type '" + + this.stack().peek() + + "'."); + } + if (this.stack().peek(1) != Type.DOUBLE) { + this.constraintViolated( + dMUL, + "The value at the stack next-to-top is not of type 'double', but of type '" + + this.stack().peek(1) + + "'."); + } + } + + @Override + public void visitLREM(LREM lREM) { + if (this.stack().peek() != Type.LONG) { + this.constraintViolated( + lREM, + "The value at the stack top is not of type 'long', but of type '" + + this.stack().peek() + + "'."); + } + if (this.stack().peek(1) != Type.LONG) { + this.constraintViolated( + lREM, + "The value at the stack next-to-top is not of type 'long', but of type '" + + this.stack().peek(1) + + "'."); + } + } + + @Override + public void visitIOR(IOR oR) { + if (this.stack().peek() != Type.INT) { + this.constraintViolated( + oR, + "The value at the stack top is not of type 'int', but of type '" + + this.stack().peek() + + "'."); + } + if (this.stack().peek(1) != Type.INT) { + this.constraintViolated( + oR, + "The value at the stack next-to-top is not of type 'int', but of type '" + + this.stack().peek(1) + + "'."); + } + } + + @Override + public void visitISHR(ISHR sHR) { + if (this.stack().peek() != Type.INT) { + this.constraintViolated( + sHR, + "The value at the stack top is not of type 'int', but of type '" + + this.stack().peek() + + "'."); + } + if (this.stack().peek(1) != Type.INT) { + this.constraintViolated( + sHR, + "The value at the stack next-to-top is not of type 'int', but of type '" + + this.stack().peek(1) + + "'."); + } + } + + public void processType2(Instruction instruction, Type type) { + if (!type.equals(Type.INT)) { + this.constraintViolated( + instruction, "The 'index' is not of type int but of type " + type + "."); + } + } + + @Override + public void visitDCMPG(DCMPG dCMPG) { + if (this.stack().peek() != Type.DOUBLE) { + this.constraintViolated( + dCMPG, + "The value at the stack top is not of type 'double', but of type '" + + this.stack().peek() + + "'."); + } + if (this.stack().peek(1) != Type.DOUBLE) { + this.constraintViolated( + dCMPG, + "The value at the stack next-to-top is not of type 'double', but of type '" + + this.stack().peek(1) + + "'."); + } + } + + public void setMethodGen(MethodGen methodGen) { + this.mg = methodGen; + } + + @Override + public void visitISHL(ISHL sHL) { + if (this.stack().peek() != Type.INT) { + this.constraintViolated( + sHL, + "The value at the stack top is not of type 'int', but of type '" + + this.stack().peek() + + "'."); + } + if (this.stack().peek(1) != Type.INT) { + this.constraintViolated( + sHL, + "The value at the stack next-to-top is not of type 'int', but of type '" + + this.stack().peek(1) + + "'."); + } + } + + @Override + public void visitDUP(DUP dUP) { + if (this.stack().peek().getSize() != 1) { + this.constraintViolated( + dUP, + "Won't DUP type on stack top '" + + this.stack().peek() + + "' because it must occupy exactly one slot, not '" + + this.stack().peek().getSize() + + "'."); + } + } + + @Override + public void visitASTORE(ASTORE aSTORE) { + if (!(this.stack().peek() instanceof ReferenceType) + && !(this.stack().peek() instanceof ReturnaddressType)) { + this.constraintViolated( + aSTORE, + "The 'objectref' is not of a ReferenceType or of ReturnaddressType but of " + + this.stack().peek() + + "."); + } + } + + @Override + public void visitRETURN(RETURN rETURN) { + if (this.mg.getName().equals("") + && Frame._this != null + && !this.mg.getClass_name().equals(Type.OBJECT.getClassName())) { + this.constraintViolated( + rETURN, "Leaving a constructor that itself did not call a constructor."); + } + } + + @Override + public void visitINEG(INEG nEG) { + if (this.stack().peek() != Type.INT) { + this.constraintViolated( + nEG, + "The value at the stack top is not of type 'int', but of type '" + + this.stack().peek() + + "'."); + } + } + + @Override + public void visitIFEQ(IFEQ fEQ) { + if (this.stack().peek() != Type.INT) { + this.constraintViolated( + fEQ, + "The value at the stack top is not of type 'int', but of type '" + + this.stack().peek() + + "'."); + } + } + + @Override + public void visitIFGT(IFGT fGT) { + if (this.stack().peek() != Type.INT) { + this.constraintViolated( + fGT, + "The value at the stack top is not of type 'int', but of type '" + + this.stack().peek() + + "'."); + } + } + + @Override + public void visitRET(RET rET) { + if (!(this.locals().get(rET.getIndex()) instanceof ReturnaddressType)) { + this.constraintViolated( + rET, "Expecting a ReturnaddressType in local variable " + rET.getIndex() + "."); + } + if (this.locals().get(rET.getIndex()) == ReturnaddressType.NO_TARGET) { + throw new AssertionViolatedException("Oops: RET expecting a target!"); + } + } + + @Override + public void visitI2F(I2F i2F) { + if (this.stack().peek() != Type.INT) { + this.constraintViolated( + i2F, + "The value at the stack top is not of type 'int', but of type '" + + this.stack().peek() + + "'."); + } + } + + @Override + public void visitIF_ICMPLT(IF_ICMPLT f_ICMPLT) { + if (this.stack().peek() != Type.INT) { + this.constraintViolated( + f_ICMPLT, + "The value at the stack top is not of type 'int', but of type '" + + this.stack().peek() + + "'."); + } + if (this.stack().peek(1) != Type.INT) { + this.constraintViolated( + f_ICMPLT, + "The value at the stack next-to-top is not of type 'int', but of type '" + + this.stack().peek(1) + + "'."); + } + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/structurals/InstructionContext.java b/src/main/java/com/allatori/lib/bcel/verifier/structurals/InstructionContext.java new file mode 100644 index 0000000..bab1b8c --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/structurals/InstructionContext.java @@ -0,0 +1,27 @@ +package com.allatori.lib.bcel.verifier.structurals; + +import com.allatori.lib.bcel.generic.InstructionHandle; +import java.util.ArrayList; + +public interface InstructionContext { + + Frame getOutFrame(ArrayList values); + + InstructionContext[] getSuccessors(); + + InstructionHandle getInstruction(); + + int getTag(); + + ExceptionHandler[] getExceptionHandlers(); + + boolean execute( + Frame frame, + ArrayList values, + InstConstraintVisitor instConstraintVisitor, + ExecutionVisitor executionVisitor); + + void setTag(int value); + + Frame getInFrame(); +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/structurals/LocalVariables.java b/src/main/java/com/allatori/lib/bcel/verifier/structurals/LocalVariables.java new file mode 100644 index 0000000..c8830d2 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/structurals/LocalVariables.java @@ -0,0 +1,147 @@ +package com.allatori.lib.bcel.verifier.structurals; + +import com.allatori.lib.bcel.generic.ReferenceType; +import com.allatori.lib.bcel.generic.Type; +import com.allatori.lib.bcel.verifier.exc.AssertionViolatedException; +import com.allatori.lib.bcel.verifier.exc.StructuralCodeConstraintException; + +public class LocalVariables { + + public Type[] locals; + + public LocalVariables getClone() { + return (LocalVariables) this.clone(); + } + + public LocalVariables(int value) { + this.locals = new Type[value]; + int value2; + for (int value3 = value2 = 0; value3 < value; value3 = value2) { + Type type = Type.UNKNOWN; + int value4 = value2; + Type[] types = this.locals; + value2++; + types[value4] = type; + } + } + + @Override + public Object clone() { + LocalVariables localVariables = new LocalVariables(this.locals.length); + int value; + for (int value2 = value = 0; value2 < this.locals.length; value2 = value) { + Type type = this.locals[value]; + int value3 = value; + Type[] types = localVariables.locals; + value++; + types[value3] = type; + } + return localVariables; + } + + public Type get(int value) { + return this.locals[value]; + } + + @Override + public int hashCode() { + return this.locals.length; + } + + public void merge(LocalVariables localVariables) { + if (this.locals.length != localVariables.locals.length) { + throw new AssertionViolatedException( + "Merging LocalVariables of different size?!? From different methods or what?!?"); + } + int value; + for (int value2 = value = 0; value2 < this.locals.length; value2 = value) { + int value3 = value; + value++; + this.merge(localVariables, value3); + } + } + + public void merge(LocalVariables localVariables, int value) { + try { + if (!(this.locals[value] instanceof UninitializedObjectType) + && localVariables.locals[value] instanceof UninitializedObjectType) { + throw new StructuralCodeConstraintException( + "Backwards branch with an uninitialized object in the local variables detected."); + } + if (!this.locals[value].equals(localVariables.locals[value]) + && this.locals[value] instanceof UninitializedObjectType + && localVariables.locals[value] instanceof UninitializedObjectType) { + throw new StructuralCodeConstraintException( + "Backwards branch with an uninitialized object in the local variables detected."); + } + if (this.locals[value] instanceof UninitializedObjectType + && !(localVariables.locals[value] instanceof UninitializedObjectType)) { + this.locals[value] = ((UninitializedObjectType) this.locals[value]).getInitialized(); + } + if (this.locals[value] instanceof ReferenceType + && localVariables.locals[value] instanceof ReferenceType) { + if (!this.locals[value].equals(localVariables.locals[value])) { + ReferenceType referenceType; + if ((referenceType = + ((ReferenceType) this.locals[value]) + .createReferenceType((ReferenceType) localVariables.locals[value])) + != null) { + this.locals[value] = referenceType; + return; + } + throw new AssertionViolatedException( + ("Could not load all the super classes of '" + + this.locals[value] + + "' and '" + + localVariables.locals[value] + + "'.")); + } + } else if (!this.locals[value].equals(localVariables.locals[value])) { + this.locals[value] = Type.UNKNOWN; + return; + } + } catch (ClassNotFoundException classNotFoundException) { + throw new AssertionViolatedException(("Missing class: " + classNotFoundException.toString())); + } + } + + public void set(int value, Type type) { + if (type != Type.BYTE && type != Type.SHORT && type != Type.BOOLEAN && type != Type.CHAR) { + this.locals[value] = type; + } else { + throw new AssertionViolatedException( + ("LocalVariables do not know about '" + type + "'. Use Type.INT instead.")); + } + } + + public int getLocals() { + return this.locals.length; + } + + @Override + public boolean equals(Object result) { + if (!(result instanceof LocalVariables)) { + return false; + } + LocalVariables localVariables = (LocalVariables) result; + if (this.locals.length != localVariables.locals.length) { + return false; + } + int value; + for (int value2 = value = 0; value2 < this.locals.length; value2 = ++value) { + if (!this.locals[value].equals(localVariables.locals[value])) { + return false; + } + } + return true; + } + + public void initializeObject(UninitializedObjectType uninitializedObjectType) { + int value; + for (int value2 = value = 0; value2 < this.locals.length; value2 = ++value) { + if (this.locals[value] == uninitializedObjectType) { + this.locals[value] = uninitializedObjectType.getInitialized(); + } + } + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/structurals/OperandStack.java b/src/main/java/com/allatori/lib/bcel/verifier/structurals/OperandStack.java new file mode 100644 index 0000000..cab8b14 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/structurals/OperandStack.java @@ -0,0 +1,175 @@ +package com.allatori.lib.bcel.verifier.structurals; + +import com.allatori.lib.bcel.generic.ObjectType; +import com.allatori.lib.bcel.generic.ReferenceType; +import com.allatori.lib.bcel.generic.Type; +import com.allatori.lib.bcel.verifier.exc.AssertionViolatedException; +import com.allatori.lib.bcel.verifier.exc.StructuralCodeConstraintException; +import java.util.ArrayList; + +public class OperandStack { + + public int maxStack; + + public ArrayList stack; + + public boolean isEmpty() { + return this.stack.isEmpty(); + } + + public int slotsUsed() { + int value = 0; + int value2; + for (int value3 = value2 = 0; value3 < this.stack.size(); value3 = value2) { + Type type = this.peek(value2); + int value4 = value; + value2++; + value = value4 + type.getSize(); + } + return value; + } + + public int size() { + return this.stack.size(); + } + + public void clear() { + this.stack = new ArrayList(); + } + + @Override + public int hashCode() { + return this.stack.hashCode(); + } + + public OperandStack getClone() { + return (OperandStack) this.clone(); + } + + public void merge(OperandStack operandStack) { + try { + if (this.slotsUsed() == operandStack.slotsUsed() && this.size() == operandStack.size()) { + for (int index = 0; index < this.size(); index++) { + if (!(this.stack.get(index) instanceof UninitializedObjectType) + && operandStack.stack.get(index) instanceof UninitializedObjectType) { + throw new StructuralCodeConstraintException( + "Backwards branch with an uninitialized object on the stack detected."); + } + if (!this.stack.get(index).equals(operandStack.stack.get(index)) + && this.stack.get(index) instanceof UninitializedObjectType + && !(operandStack.stack.get(index) instanceof UninitializedObjectType)) { + throw new StructuralCodeConstraintException( + "Backwards branch with an uninitialized object on the stack detected."); + } + if (this.stack.get(index) instanceof UninitializedObjectType + && !(operandStack.stack.get(index) instanceof UninitializedObjectType)) { + this.stack.set( + index, ((UninitializedObjectType) this.stack.get(index)).getInitialized()); + } + if (!this.stack.get(index).equals(operandStack.stack.get(index))) { + if (!(this.stack.get(index) instanceof ReferenceType) + || !(operandStack.stack.get(index) instanceof ReferenceType)) { + throw new StructuralCodeConstraintException( + ("Cannot merge stacks of different types:\nStack A:\n" + + this + + "\nStack B:\n" + + operandStack)); + } + this.stack.set( + index, + ((ReferenceType) this.stack.get(index)) + .createReferenceType((ReferenceType) operandStack.stack.get(index))); + } + } + } else { + throw new StructuralCodeConstraintException( + ("Cannot merge stacks of different size:\nOperandStack A:\n" + + this + + "\nOperandStack B:\n" + + operandStack)); + } + } catch (ClassNotFoundException classNotFoundException) { + throw new AssertionViolatedException(("Missing class: " + classNotFoundException.toString())); + } + } + + @Override + public Object clone() { + OperandStack operandStack; + (operandStack = new OperandStack(this.maxStack)).stack = (ArrayList) this.stack.clone(); + return operandStack; + } + + public void push(Type type) { + if (type == null) { + throw new AssertionViolatedException("Cannot push NULL onto OperandStack."); + } + if (type != Type.BOOLEAN && type != Type.CHAR && type != Type.BYTE && type != Type.SHORT) { + if (this.slotsUsed() >= this.maxStack) { + throw new AssertionViolatedException( + ("OperandStack too small, should have thrown proper Exception elsewhere. Stack: " + + this)); + } + this.stack.add(type); + } else { + throw new AssertionViolatedException( + ("The OperandStack does not know about '" + type + "'; use Type.INT instead.")); + } + } + + public Type peek(int value) { + return (Type) this.stack.get(this.size() - value - 1); + } + + public void initializeObject(UninitializedObjectType uninitializedObjectType) { + int value; + for (int value2 = value = 0; value2 < this.stack.size(); value2 = ++value) { + if (this.stack.get(value) == uninitializedObjectType) { + this.stack.set(value, uninitializedObjectType.getInitialized()); + } + } + } + + public OperandStack(int maxStack, ObjectType objectType) { + super(); + this.stack = new ArrayList(); + this.maxStack = maxStack; + this.push(objectType); + } + + public OperandStack(int maxStack) { + super(); + this.stack = new ArrayList(); + this.maxStack = maxStack; + } + + @Override + public boolean equals(Object result) { + if (!(result instanceof OperandStack)) { + return false; + } + OperandStack operandStack = (OperandStack) result; + return this.stack.equals(operandStack.stack); + } + + public Type pop() { + return (Type) this.stack.remove(this.size() - 1); + } + + public int maxStack() { + return this.maxStack; + } + + public Type pop(int value) { + int value2; + for (int value3 = value2 = 0; value3 < value; value3 = value2) { + value2++; + this.pop(); + } + return null; + } + + public Type peek() { + return this.peek(0); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/structurals/Pass3bVerifier$1.java b/src/main/java/com/allatori/lib/bcel/verifier/structurals/Pass3bVerifier$1.java new file mode 100644 index 0000000..e7b6a57 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/structurals/Pass3bVerifier$1.java @@ -0,0 +1,3 @@ +package com.allatori.lib.bcel.verifier.structurals; + +public class Pass3bVerifier$1 {} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/structurals/Pass3bVerifier$InstructionContextQueue.java b/src/main/java/com/allatori/lib/bcel/verifier/structurals/Pass3bVerifier$InstructionContextQueue.java new file mode 100644 index 0000000..4d835d9 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/structurals/Pass3bVerifier$InstructionContextQueue.java @@ -0,0 +1,50 @@ +package com.allatori.lib.bcel.verifier.structurals; + +import java.util.ArrayList; +import java.util.List; +import java.util.Vector; + +public final class Pass3bVerifier$InstructionContextQueue { + + public List ecs; + + public List ics = new Vector(); + + public Pass3bVerifier$InstructionContextQueue(Pass3bVerifier$1 pass3bVerifier$1) { + this(); + } + + public ArrayList getEC(int value) { + return (ArrayList) this.ecs.get(value); + } + + public int size() { + return this.ics.size(); + } + + public InstructionContext getIC(int value) { + return (InstructionContext) this.ics.get(value); + } + + public Pass3bVerifier$InstructionContextQueue() { + this.ecs = new Vector(); + } + + public boolean isEmpty() { + return this.ics.isEmpty(); + } + + public void add(InstructionContext instructionContext, ArrayList values) { + this.ics.add(instructionContext); + this.ecs.add(values); + } + + public void remove(int value) { + this.ics.remove(value); + this.ecs.remove(value); + } + + public void remove() { + this.remove(0); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/structurals/Pass3bVerifier.java b/src/main/java/com/allatori/lib/bcel/verifier/structurals/Pass3bVerifier.java new file mode 100644 index 0000000..ed18fc5 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/structurals/Pass3bVerifier.java @@ -0,0 +1,273 @@ +package com.allatori.lib.bcel.verifier.structurals; + +import com.allatori.lib.bcel.Repository; +import com.allatori.lib.bcel.classfile.JavaClass; +import com.allatori.lib.bcel.classfile.Method; +import com.allatori.lib.bcel.generic.ConstantPoolGen; +import com.allatori.lib.bcel.generic.InstructionHandle; +import com.allatori.lib.bcel.generic.JsrInstruction; +import com.allatori.lib.bcel.generic.MethodGen; +import com.allatori.lib.bcel.generic.ObjectType; +import com.allatori.lib.bcel.generic.RET; +import com.allatori.lib.bcel.generic.ReturnInstruction; +import com.allatori.lib.bcel.generic.ReturnaddressType; +import com.allatori.lib.bcel.generic.Type; +import com.allatori.lib.bcel.verifier.PassVerifier; +import com.allatori.lib.bcel.verifier.VerificationResult; +import com.allatori.lib.bcel.verifier.Verifier; +import com.allatori.lib.bcel.verifier.exc.AssertionViolatedException; +import com.allatori.lib.bcel.verifier.exc.VerifierConstraintViolatedException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.Random; + +public final class Pass3bVerifier extends PassVerifier { + + public Verifier myOwner; + + public static final boolean DEBUG = true; + + public int method_no; + + @Override + public VerificationResult getVerificationResult() { + if (!this.myOwner.doPass3a(this.method_no).equals(VerificationResult.VERIFICATION_RESULT2)) { + return VerificationResult.VERIFICATION_RESULT; + } + JavaClass javaClass; + try { + javaClass = Repository.lookupClass(this.myOwner.getClassName()); + } catch (ClassNotFoundException classNotFoundException) { + throw new AssertionViolatedException(("Missing class: " + classNotFoundException.toString())); + } + ConstantPoolGen constantPoolGen = new ConstantPoolGen(javaClass.getConstantPool()); + InstConstraintVisitor instConstraintVisitor; + (instConstraintVisitor = new InstConstraintVisitor()).setConstantPoolGen(constantPoolGen); + ExecutionVisitor executionVisitor = new ExecutionVisitor(); + executionVisitor.setConstantPoolGen(constantPoolGen); + Method[] methods = javaClass.getMethods(); + try { + MethodGen methodGen = + new MethodGen(methods[this.method_no], this.myOwner.getClassName(), constantPoolGen); + instConstraintVisitor.setMethodGen(methodGen); + if (!methodGen.isEnabled15() && !methodGen.isEnabled14()) { + ControlFlowGraph controlFlowGraph; + Frame frame; + MethodGen methodGen2; + label68: + { + controlFlowGraph = new ControlFlowGraph(methodGen); + frame = new Frame(methodGen.getCount(), methodGen.getCount2()); + if (!methodGen.isEnabled11()) { + if (methodGen.getName().equals("")) { + Frame._this = new UninitializedObjectType(new ObjectType(javaClass.getText2())); + methodGen2 = methodGen; + frame.getLocals().set(0, Frame._this); + break label68; + } + Frame._this = null; + LocalVariables locals = frame.getLocals(); + locals.set(0, new ObjectType(javaClass.getText2())); + } + methodGen2 = methodGen; + } + Type[] argumentTypes = methodGen2.getArgumentTypes(); + int value = 0; + int value2; + for (int value3 = value2 = 0; value3 < argumentTypes.length; value3 = ++value2) { + if (argumentTypes[value2] == Type.SHORT + || argumentTypes[value2] == Type.BYTE + || argumentTypes[value2] == Type.CHAR + || argumentTypes[value2] == Type.BOOLEAN) { + argumentTypes[value2] = Type.INT; + } + frame + .getLocals() + .set(value + value2 + (methodGen.isEnabled11() ? 0 : 1), argumentTypes[value2]); + if (argumentTypes[value2].getSize() == 2) { + LocalVariables locals2 = frame.getLocals(); + locals2.set(++value + value2 + (methodGen.isEnabled11() ? 0 : 1), Type.UNKNOWN); + } + } + this.circulationPump( + controlFlowGraph, + controlFlowGraph.contextOf(methodGen.getInstructionList().getStart()), + frame, + instConstraintVisitor, + executionVisitor); + } + } catch (VerifierConstraintViolatedException verifierConstraintViolatedException) { + verifierConstraintViolatedException.extendMessage( + "Constraint violated in method '" + methods[this.method_no] + "':\n", ""); + return new VerificationResult(2, verifierConstraintViolatedException.getMessage()); + } catch (RuntimeException runtimeException) { + StringWriter stringWriter = new StringWriter(); + PrintWriter printWriter = new PrintWriter(stringWriter); + runtimeException.printStackTrace(printWriter); + throw new AssertionViolatedException( + ("Some RuntimeException occured while verify()ing class '" + + javaClass.getText2() + + "', method '" + + methods[this.method_no] + + "'. Original RuntimeException's stack trace:\n---\n" + + stringWriter + + "---\n")); + } + return VerificationResult.VERIFICATION_RESULT2; + } + + public Pass3bVerifier(Verifier verifier, int method_no) { + super(); + this.myOwner = verifier; + this.method_no = method_no; + } + + public int getMethodNo() { + return this.method_no; + } + + public void circulationPump( + ControlFlowGraph controlFlowGraph, + InstructionContext instructionContext, + Frame frame, + InstConstraintVisitor instConstraintVisitor, + ExecutionVisitor executionVisitor) { + InstructionContext instructionContext2; + new Random(); + Pass3bVerifier$InstructionContextQueue pass3bVerifier$InstructionContextQueue = + new Pass3bVerifier$InstructionContextQueue(null); + instructionContext.execute(frame, new ArrayList(), instConstraintVisitor, executionVisitor); + pass3bVerifier$InstructionContextQueue.add(instructionContext, new ArrayList()); + while (!pass3bVerifier$InstructionContextQueue.isEmpty()) { + InstructionContext iC = pass3bVerifier$InstructionContextQueue.getIC(0); + ArrayList eC = pass3bVerifier$InstructionContextQueue.getEC(0); + pass3bVerifier$InstructionContextQueue.remove(0); + ArrayList values = (ArrayList) eC.clone(); + ArrayList values2; + (values2 = (ArrayList) eC.clone()).add(iC); + if (!(iC.getInstruction().getInstruction() instanceof RET)) { + InstructionContext[] successors = iC.getSuccessors(); + int value; + for (int value2 = value = 0; value2 < successors.length; value2 = ++value) { + InstructionContext instructionContext3; + if ((instructionContext3 = successors[value]) + .execute(iC.getOutFrame(values), values2, instConstraintVisitor, executionVisitor)) { + pass3bVerifier$InstructionContextQueue.add( + instructionContext3, (ArrayList) values2.clone()); + } + } + } else { + RET rET = (RET) iC.getInstruction().getInstruction(); + ReturnaddressType returnaddressType = + (ReturnaddressType) iC.getOutFrame(values).getLocals().get(rET.getIndex()); + InstructionContext instructionContext4 = + controlFlowGraph.contextOf(returnaddressType.getTarget()); + InstructionContext instructionContext5 = null; + int value3 = 0; + int value4; + int value5 = value4 = values.size() - 1; + while (true) { + if (value5 < 0) { + instructionContext2 = instructionContext5; + break; + } + if (value3 < 0) { + throw new AssertionViolatedException("More RET than JSR in execution chain?!"); + } + if (((InstructionContext) values.get(value4)).getInstruction().getInstruction() + instanceof JsrInstruction) { + if (value3 == 0) { + instructionContext2 = instructionContext5 = (InstructionContext) values.get(value4); + break; + } + value3--; + } + if (((InstructionContext) values.get(value4)).getInstruction().getInstruction() + instanceof RET) { + value3++; + } + value5 = --value4; + } + if (instructionContext2 == null) { + throw new AssertionViolatedException( + ("RET without a JSR before in ExecutionChain?! EC: '" + values + "'.")); + } + JsrInstruction jsrInstruction = + (JsrInstruction) instructionContext5.getInstruction().getInstruction(); + if (instructionContext4 != controlFlowGraph.contextOf(jsrInstruction.physicalSuccessor())) { + throw new AssertionViolatedException( + ("RET '" + + iC.getInstruction() + + "' info inconsistent: jump back to '" + + instructionContext4 + + "' or '" + + controlFlowGraph.contextOf(jsrInstruction.physicalSuccessor()) + + "'?")); + } + if (instructionContext4.execute( + iC.getOutFrame(values), values2, instConstraintVisitor, executionVisitor)) { + pass3bVerifier$InstructionContextQueue.add( + instructionContext4, (ArrayList) values2.clone()); + } + } + ExceptionHandler[] exceptionHandlers = iC.getExceptionHandlers(); + int value6; + for (int value7 = value6 = 0; value7 < exceptionHandlers.length; value7 = ++value6) { + InstructionContext instructionContext6; + if ((instructionContext6 = + controlFlowGraph.contextOf(exceptionHandlers[value6].getHandlerStart())) + .execute( + new Frame( + iC.getOutFrame(values).getLocals(), + new OperandStack( + iC.getOutFrame(values).getStack().maxStack(), + exceptionHandlers[value6].getExceptionType() == null + ? Type.THROWABLE + : exceptionHandlers[value6].getExceptionType())), + new ArrayList(), + instConstraintVisitor, + executionVisitor)) { + pass3bVerifier$InstructionContextQueue.add(instructionContext6, new ArrayList()); + } + } + } + InstructionHandle instruction = instructionContext.getInstruction(); + do { + if (instruction.getInstruction() instanceof ReturnInstruction + && !controlFlowGraph.isDead(instruction)) { + Frame frame2; + InstructionContext instructionContext7; + LocalVariables locals = + (frame2 = + (instructionContext7 = controlFlowGraph.contextOf(instruction)) + .getOutFrame(new ArrayList())) + .getLocals(); + int value8; + for (int value9 = value8 = 0; value9 < locals.getLocals(); value9 = ++value8) { + if (locals.get(value8) instanceof UninitializedObjectType) { + this.addMessage( + "Warning: ReturnInstruction '" + + instructionContext7 + + "' may leave method with an uninitialized object in the local variables array" + + " '" + + locals + + "'."); + } + } + OperandStack stack = frame2.getStack(); + int value10; + for (int value11 = value10 = 0; value11 < stack.size(); value11 = ++value10) { + if (stack.peek(value10) instanceof UninitializedObjectType) { + this.addMessage( + "Warning: ReturnInstruction '" + + instructionContext7 + + "' may leave method with an uninitialized object on the operand stack '" + + stack + + "'."); + } + } + } + } while ((instruction = instruction.getInstructionHandle2()) != null); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/structurals/Subroutine.java b/src/main/java/com/allatori/lib/bcel/verifier/structurals/Subroutine.java new file mode 100644 index 0000000..50d6290 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/structurals/Subroutine.java @@ -0,0 +1,20 @@ +package com.allatori.lib.bcel.verifier.structurals; + +import com.allatori.lib.bcel.generic.InstructionHandle; + +public interface Subroutine { + + int[] getCounts(); + + boolean contains(InstructionHandle instructionHandle); + + InstructionHandle getLeavingRET(); + + Subroutine[] subSubs(); + + int[] getCounts2(); + + InstructionHandle[] getInstructionHandles(); + + InstructionHandle[] getInstructionHandles2(); +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/structurals/Subroutines$SubroutineImpl.java b/src/main/java/com/allatori/lib/bcel/verifier/structurals/Subroutines$SubroutineImpl.java new file mode 100644 index 0000000..35f7ec4 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/structurals/Subroutines$SubroutineImpl.java @@ -0,0 +1,236 @@ +package com.allatori.lib.bcel.verifier.structurals; + +import com.allatori.lib.bcel.generic.ASTORE; +import com.allatori.lib.bcel.generic.IndexedInstruction; +import com.allatori.lib.bcel.generic.Instruction; +import com.allatori.lib.bcel.generic.InstructionHandle; +import com.allatori.lib.bcel.generic.JsrInstruction; +import com.allatori.lib.bcel.generic.LocalVariableInstruction; +import com.allatori.lib.bcel.generic.RET; +import com.allatori.lib.bcel.verifier.exc.AssertionViolatedException; +import com.allatori.lib.bcel.verifier.exc.StructuralCodeConstraintException; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +public class Subroutines$SubroutineImpl implements Subroutine { + + public int localVariable; + + public Set theJSRs; + + public final Subroutines this$0; + + public Set instructions; + + public static final int UNSET = -1; + + public InstructionHandle theRET; + + public void setLeavingRET() { + if (this.localVariable == -1) { + throw new AssertionViolatedException( + "setLeavingRET() called for top-level 'subroutine' or forgot to set local variable" + + " first."); + } + Iterator iterator2 = this.instructions.iterator(); + InstructionHandle instructionHandle = null; + while (iterator2.hasNext()) { + InstructionHandle instructionHandle2; + if ((instructionHandle2 = (InstructionHandle) iterator2.next()).getInstruction() + instanceof RET) { + if (instructionHandle != null) { + throw new StructuralCodeConstraintException( + ("Subroutine with more then one RET detected: '" + + instructionHandle + + "' and '" + + instructionHandle2 + + "'.")); + } + instructionHandle = instructionHandle2; + } + } + if (instructionHandle == null) { + throw new StructuralCodeConstraintException("Subroutine without a RET detected."); + } + if (((RET) instructionHandle.getInstruction()).getIndex() != this.localVariable) { + throw new StructuralCodeConstraintException( + ("Subroutine uses '" + + instructionHandle + + "' which does not match the correct local variable '" + + this.localVariable + + "'.")); + } + this.theRET = instructionHandle; + } + + @Override + public InstructionHandle[] getInstructionHandles() { + if (this == this.this$0.TOPLEVEL) { + throw new AssertionViolatedException( + "getLeavingRET() called on top level pseudo-subroutine."); + } + InstructionHandle[] instructionHandles = new InstructionHandle[this.theJSRs.size()]; + return (InstructionHandle[]) this.theJSRs.toArray(instructionHandles); + } + + @Override + public InstructionHandle[] getInstructionHandles2() { + InstructionHandle[] instructionHandles = new InstructionHandle[this.instructions.size()]; + return (InstructionHandle[]) this.instructions.toArray(instructionHandles); + } + + public void setLocalVariable(int localVariable) { + if (this.localVariable != -1) { + throw new AssertionViolatedException("localVariable set twice."); + } + this.localVariable = localVariable; + } + + public void _getRecursivelyAccessedLocalsIndicesHelper(Set values, Subroutine[] subroutines) { + int value; + for (int value2 = value = 0; value2 < subroutines.length; value2 = ++value) { + int[] counts2 = subroutines[value].getCounts2(); + int value3; + for (int value4 = value3 = 0; value4 < counts2.length; value4 = value3) { + values.add(new Integer(counts2[value3++])); + } + if (subroutines[value].subSubs().length != 0) { + this._getRecursivelyAccessedLocalsIndicesHelper(values, subroutines[value].subSubs()); + } + } + } + + public static Set access$100(Subroutines$SubroutineImpl subroutines$SubroutineImpl) { + return subroutines$SubroutineImpl.theJSRs; + } + + @Override + public boolean contains(InstructionHandle instructionHandle) { + return this.instructions.contains(instructionHandle); + } + + @Override + public int[] getCounts() { + HashSet values = new HashSet(); + int[] counts2 = this.getCounts2(); + int value; + for (int value2 = value = 0; value2 < counts2.length; value2 = value) { + values.add(new Integer(counts2[value++])); + } + this._getRecursivelyAccessedLocalsIndicesHelper(values, this.subSubs()); + int[] values2 = new int[values.size()]; + Iterator iterator2 = values.iterator(); + int value3 = -1; + for (Iterator iterator3 = iterator2; iterator3.hasNext(); iterator3 = iterator2) { + values2[++value3] = (Integer) iterator2.next(); + } + return values2; + } + + public static InstructionHandle access$200( + Subroutines$SubroutineImpl subroutines$SubroutineImpl) { + return subroutines$SubroutineImpl.theRET; + } + + public static int access$000(Subroutines$SubroutineImpl subroutines$SubroutineImpl) { + return subroutines$SubroutineImpl.localVariable; + } + + public Subroutines$SubroutineImpl(Subroutines subroutines) { + super(); + this.this$0 = subroutines; + this.localVariable = -1; + this.instructions = new HashSet(); + this.theJSRs = new HashSet(); + } + + public void addInstruction(InstructionHandle instructionHandle) { + if (this.theRET != null) { + throw new AssertionViolatedException( + "All instructions must have been added before invoking setLeavingRET()."); + } + this.instructions.add(instructionHandle); + } + + @Override + public Subroutine[] subSubs() { + HashSet values = new HashSet(); + Iterator iterator2 = this.instructions.iterator(); + while (iterator2.hasNext()) { + Instruction instruction; + if ((instruction = ((InstructionHandle) iterator2.next()).getInstruction()) + instanceof JsrInstruction) { + InstructionHandle target = ((JsrInstruction) instruction).getTarget(); + values.add(this.this$0.getSubroutine(target)); + } + } + Subroutine[] subroutines = new Subroutine[values.size()]; + return (Subroutine[]) values.toArray(subroutines); + } + + public void addEnteringJsrInstruction(InstructionHandle instructionHandle) { + if (instructionHandle == null + || !(instructionHandle.getInstruction() instanceof JsrInstruction)) { + throw new AssertionViolatedException("Expecting JsrInstruction InstructionHandle."); + } + if (this.localVariable == -1) { + throw new AssertionViolatedException("Set the localVariable first!"); + } + if (this.localVariable + != ((ASTORE) + ((JsrInstruction) instructionHandle.getInstruction()).getTarget().getInstruction()) + .getIndex()) { + throw new AssertionViolatedException("Setting a wrong JsrInstruction."); + } + this.theJSRs.add(instructionHandle); + } + + @Override + public int[] getCounts2() { + HashSet values = new HashSet(); + if (this.theRET == null && this != this.this$0.TOPLEVEL) { + throw new AssertionViolatedException( + "This subroutine object must be built up completely before calculating accessed locals."); + } + Iterator iterator2 = this.instructions.iterator(); + while (iterator2.hasNext()) { + InstructionHandle instructionHandle; + if ((instructionHandle = (InstructionHandle) iterator2.next()).getInstruction() + instanceof LocalVariableInstruction + || instructionHandle.getInstruction() instanceof RET) { + int index = ((IndexedInstruction) instructionHandle.getInstruction()).getIndex(); + values.add(new Integer(index)); + try { + if (instructionHandle.getInstruction() instanceof LocalVariableInstruction + && ((LocalVariableInstruction) instructionHandle.getInstruction()) + .getType(null) + .getSize() + == 2) { + values.add(new Integer(index + 1)); + } + } catch (RuntimeException runtimeException) { + throw new AssertionViolatedException( + "Oops. BCEL did not like NULL as a ConstantPoolGen object."); + } + } + } + int[] values2 = new int[values.size()]; + Iterator iterator3 = values.iterator(); + int value = -1; + for (Iterator iterator4 = iterator3; iterator4.hasNext(); iterator4 = iterator3) { + values2[++value] = (Integer) iterator3.next(); + } + return values2; + } + + @Override + public InstructionHandle getLeavingRET() { + if (this == this.this$0.TOPLEVEL) { + throw new AssertionViolatedException( + "getLeavingRET() called on top level pseudo-subroutine."); + } else { + return this.theRET; + } + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/structurals/Subroutines.java b/src/main/java/com/allatori/lib/bcel/verifier/structurals/Subroutines.java new file mode 100644 index 0000000..da5f983 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/structurals/Subroutines.java @@ -0,0 +1,255 @@ +package com.allatori.lib.bcel.verifier.structurals; + +import com.allatori.lib.bcel.generic.ASTORE; +import com.allatori.lib.bcel.generic.ATHROW; +import com.allatori.lib.bcel.generic.BranchInstruction; +import com.allatori.lib.bcel.generic.CodeExceptionGen; +import com.allatori.lib.bcel.generic.GotoInstruction; +import com.allatori.lib.bcel.generic.Instruction; +import com.allatori.lib.bcel.generic.InstructionHandle; +import com.allatori.lib.bcel.generic.JsrInstruction; +import com.allatori.lib.bcel.generic.MethodGen; +import com.allatori.lib.bcel.generic.RET; +import com.allatori.lib.bcel.generic.ReturnInstruction; +import com.allatori.lib.bcel.generic.Select; +import com.allatori.lib.bcel.verifier.exc.AssertionViolatedException; +import com.allatori.lib.bcel.verifier.exc.StructuralCodeConstraintException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +public class Subroutines { + + public Map entries; + + public final Subroutine TOPLEVEL; + + public static final Integer INTEGER3 = new Integer(0); + + public static final Integer INTEGER2 = new Integer(1); + + public static final Integer INTEGER = new Integer(2); + + public Subroutine subroutineOf(InstructionHandle instructionHandle) { + Iterator iterator2 = this.entries.values().iterator(); + while (iterator2.hasNext()) { + Subroutine subroutine; + if ((subroutine = (Subroutine) iterator2.next()).contains(instructionHandle)) { + return subroutine; + } + } + System.err.println("DEBUG: Please verify '" + instructionHandle + "' lies in dead code."); + return null; + } + + public static InstructionHandle[] getSuccessors(InstructionHandle instructionHandle) { + InstructionHandle[] instructionHandles = new InstructionHandle[0]; + InstructionHandle[] instructionHandles2 = new InstructionHandle[1]; + InstructionHandle[] instructionHandles3 = new InstructionHandle[2]; + Instruction instruction; + if ((instruction = instructionHandle.getInstruction()) instanceof RET) { + return instructionHandles; + } + if (instruction instanceof ReturnInstruction) { + return instructionHandles; + } + if (instruction instanceof ATHROW) { + return instructionHandles; + } + if (instruction instanceof JsrInstruction) { + instructionHandles2[0] = instructionHandle.getInstructionHandle2(); + return instructionHandles2; + } + if (instruction instanceof GotoInstruction) { + instructionHandles2[0] = ((GotoInstruction) instruction).getTarget(); + return instructionHandles2; + } + if (instruction instanceof BranchInstruction) { + if (instruction instanceof Select) { + InstructionHandle[] instructionHandles4; + InstructionHandle[] instructionHandles5; + (instructionHandles5 = + new InstructionHandle + [(instructionHandles4 = ((Select) instruction).getTargets()).length + 1]) + [0] = + ((Select) instruction).getTarget(); + System.arraycopy( + instructionHandles4, 0, instructionHandles5, 1, instructionHandles4.length); + return instructionHandles5; + } else { + instructionHandles3[0] = instructionHandle.getInstructionHandle2(); + instructionHandles3[1] = ((BranchInstruction) instruction).getTarget(); + return instructionHandles3; + } + } else { + instructionHandles2[0] = instructionHandle.getInstructionHandle2(); + return instructionHandles2; + } + } + + public Subroutines(MethodGen methodGen) { + super(); + this.entries = new HashMap(); + InstructionHandle[] instructionHandles = methodGen.getInstructionList().getInstructionHandles(); + CodeExceptionGen[] exceptionHandlers = methodGen.getExceptionHandlers(); + this.TOPLEVEL = new Subroutines$SubroutineImpl(this); + HashSet values2 = new HashSet(); + int value; + for (int value2 = value = 0; value2 < instructionHandles.length; value2 = ++value) { + Instruction instruction; + if ((instruction = instructionHandles[value].getInstruction()) instanceof JsrInstruction) { + values2.add(((JsrInstruction) instruction).getTarget()); + } + } + Iterator iterator2; + Iterator iterator3 = iterator2 = values2.iterator(); + while (iterator3.hasNext()) { + Subroutines$SubroutineImpl subroutines$SubroutineImpl = new Subroutines$SubroutineImpl(this); + InstructionHandle instructionHandle = (InstructionHandle) iterator2.next(); + subroutines$SubroutineImpl.setLocalVariable( + ((ASTORE) instructionHandle.getInstruction()).getIndex()); + iterator3 = iterator2; + this.entries.put(instructionHandle, subroutines$SubroutineImpl); + } + this.entries.put(instructionHandles[0], this.TOPLEVEL); + values2.add(instructionHandles[0]); + int value3 = 0; + for (int value4 = value3; value4 < instructionHandles.length; value4 = ++value3) { + Instruction instruction2; + if ((instruction2 = instructionHandles[value3].getInstruction()) instanceof JsrInstruction) { + InstructionHandle target = ((JsrInstruction) instruction2).getTarget(); + ((Subroutines$SubroutineImpl) this.getSubroutine(target)) + .addEnteringJsrInstruction(instructionHandles[value3]); + } + } + HashSet values3 = new HashSet(); + HashMap entries2 = new HashMap(); + for (InstructionHandle instructionHandle2 : + ((Iterable) ((Iterable) values2))) { + int value5; + for (int value6 = value5 = 0; value6 < instructionHandles.length; value6 = value5) { + int value7 = value5; + value5++; + entries2.put(instructionHandles[value7], INTEGER3); + } + entries2.put(instructionHandle2, INTEGER2); + ArrayList values4; + (values4 = new ArrayList()).add(instructionHandle2); + int value8; + if (instructionHandle2 == instructionHandles[0]) { + for (int value9 = value8 = 0; value9 < exceptionHandlers.length; value9 = value8) { + entries2.put(exceptionHandlers[value8].getInstructionHandle3(), INTEGER2); + int value10 = value8; + ArrayList values5 = values4; + value8++; + values5.add(exceptionHandlers[value10].getInstructionHandle3()); + } + } + for (ArrayList values6 = values4; values6.size() != 0; values6 = values4) { + InstructionHandle instructionHandle3; + InstructionHandle[] successors = + getSuccessors(instructionHandle3 = (InstructionHandle) values4.remove(0)); + int value11; + for (int value12 = value11 = 0; value12 < successors.length; value12 = ++value11) { + if ((Integer) entries2.get(successors[value11]) == INTEGER3) { + entries2.put(successors[value11], INTEGER2); + values4.add(successors[value11]); + } + } + entries2.put(instructionHandle3, INTEGER); + } + int value13; + for (int value14 = value13 = 0; value14 < instructionHandles.length; value14 = ++value13) { + if (entries2.get(instructionHandles[value13]) == INTEGER) { + ((Subroutines$SubroutineImpl) + (instructionHandle2 == instructionHandles[0] + ? this.getTopLevel() + : this.getSubroutine(instructionHandle2))) + .addInstruction(instructionHandles[value13]); + if (values3.contains(instructionHandles[value13])) { + throw new StructuralCodeConstraintException( + ("Instruction '" + + instructionHandles[value13] + + "' is part of more than one subroutine (or of the top level and a" + + " subroutine).")); + } + values3.add(instructionHandles[value13]); + } + } + if (instructionHandle2 != instructionHandles[0]) { + ((Subroutines$SubroutineImpl) this.getSubroutine(instructionHandle2)).setLeavingRET(); + } + } + InstructionHandle instructionHandle4; + int value15; + for (int value16 = value15 = 0; value16 < exceptionHandlers.length; value16 = ++value15) { + for (InstructionHandle instructionHandle5 = + instructionHandle4 = exceptionHandlers[value15].getInstructionHandle2(); + instructionHandle5 + != exceptionHandlers[value15].getInstructionHandle().getInstructionHandle2(); + instructionHandle5 = instructionHandle4 = instructionHandle4.getInstructionHandle2()) { + Iterator iterator4 = this.entries.values().iterator(); + while (iterator4.hasNext()) { + Subroutine subroutine; + if ((subroutine = (Subroutine) iterator4.next()) + != this.entries.get(instructionHandles[0]) + && subroutine.contains(instructionHandle4)) { + throw new StructuralCodeConstraintException( + ("Subroutine instruction '" + + instructionHandle4 + + "' is protected by an exception handler, '" + + exceptionHandlers[value15] + + "'. This is forbidden by the JustIce verifier due to its clear definition of" + + " subroutines.")); + } + } + } + } + this.noRecursiveCalls(this.getTopLevel(), new HashSet()); + } + + public Subroutine getSubroutine(InstructionHandle instructionHandle) { + Subroutine subroutine; + if ((subroutine = (Subroutine) this.entries.get(instructionHandle)) == null) { + throw new AssertionViolatedException( + "Subroutine requested for an InstructionHandle that is not a leader of a subroutine."); + } else if (subroutine == this.TOPLEVEL) { + throw new AssertionViolatedException( + "TOPLEVEL special subroutine requested; use getTopLevel()."); + } else { + return subroutine; + } + } + + public void noRecursiveCalls(Subroutine subroutine, Set values) { + Subroutine[] subroutines = subroutine.subSubs(); + int value; + for (int value2 = value = 0; value2 < subroutines.length; value2 = value) { + int index = ((RET) subroutines[value].getLeavingRET().getInstruction()).getIndex(); + if (!values.add(new Integer(index))) { + Subroutines$SubroutineImpl subroutines$SubroutineImpl = + (Subroutines$SubroutineImpl) subroutines[value]; + throw new StructuralCodeConstraintException( + ("Subroutine with local variable '" + + Subroutines$SubroutineImpl.access$000(subroutines$SubroutineImpl) + + "', JSRs '" + + Subroutines$SubroutineImpl.access$100(subroutines$SubroutineImpl) + + "', RET '" + + Subroutines$SubroutineImpl.access$200(subroutines$SubroutineImpl) + + "' is called by a subroutine which uses the same local variable index as itself;" + + " maybe even a recursive call? JustIce's clean definition of a subroutine forbids" + + " both.")); + } + this.noRecursiveCalls(subroutines[value], values); + value++; + values.remove(new Integer(index)); + } + } + + public Subroutine getTopLevel() { + return this.TOPLEVEL; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/structurals/UninitializedObjectType.java b/src/main/java/com/allatori/lib/bcel/verifier/structurals/UninitializedObjectType.java new file mode 100644 index 0000000..22446ba --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/structurals/UninitializedObjectType.java @@ -0,0 +1,31 @@ +package com.allatori.lib.bcel.verifier.structurals; + +import com.allatori.lib.bcel.Constants; +import com.allatori.lib.bcel.generic.ObjectType; +import com.allatori.lib.bcel.generic.ReferenceType; + +public class UninitializedObjectType extends ReferenceType implements Constants { + + public ObjectType initialized; + + @Override + public int hashCode() { + return this.initialized.hashCode(); + } + + public ObjectType getInitialized() { + return this.initialized; + } + + @Override + public boolean equals(Object result) { + return !(result instanceof UninitializedObjectType) + ? false + : this.initialized.equals(((UninitializedObjectType) result).initialized); + } + + public UninitializedObjectType(ObjectType objectType) { + super((byte) 15, ("")); + this.initialized = objectType; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/ui/VerifierActionListener.java b/src/main/java/com/allatori/lib/bcel/verifier/ui/VerifierActionListener.java new file mode 100644 index 0000000..facded8 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/ui/VerifierActionListener.java @@ -0,0 +1,20 @@ +package com.allatori.lib.bcel.verifier.ui; + +import com.allatori.lib.bcel.verifier.VerifierAppFrame; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public class VerifierActionListener implements ActionListener { + + public final VerifierAppFrame verifierAppFrame; + + @Override + public void actionPerformed(ActionEvent actionEvent) { + this.verifierAppFrame.aboutMenuItem_actionPerformed(actionEvent); + } + + public VerifierActionListener(VerifierAppFrame verifierAppFrame2) { + super(); + this.verifierAppFrame = verifierAppFrame2; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/ui/VerifierActionListener2.java b/src/main/java/com/allatori/lib/bcel/verifier/ui/VerifierActionListener2.java new file mode 100644 index 0000000..c703613 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/ui/VerifierActionListener2.java @@ -0,0 +1,20 @@ +package com.allatori.lib.bcel.verifier.ui; + +import com.allatori.lib.bcel.verifier.VerifierAppFrame; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public class VerifierActionListener2 implements ActionListener { + + public final VerifierAppFrame verifierAppFrame; + + @Override + public void actionPerformed(ActionEvent actionEvent) { + this.verifierAppFrame.whatisMenuItem_actionPerformed(actionEvent); + } + + public VerifierActionListener2(VerifierAppFrame verifierAppFrame2) { + super(); + this.verifierAppFrame = verifierAppFrame2; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/ui/VerifierActionListener3.java b/src/main/java/com/allatori/lib/bcel/verifier/ui/VerifierActionListener3.java new file mode 100644 index 0000000..e65583f --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/ui/VerifierActionListener3.java @@ -0,0 +1,20 @@ +package com.allatori.lib.bcel.verifier.ui; + +import com.allatori.lib.bcel.verifier.VerifierAppFrame; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public class VerifierActionListener3 implements ActionListener { + + public final VerifierAppFrame verifierAppFrame; + + @Override + public void actionPerformed(ActionEvent actionEvent) { + this.verifierAppFrame.newFileMenuItem_actionPerformed(actionEvent); + } + + public VerifierActionListener3(VerifierAppFrame verifierAppFrame2) { + super(); + this.verifierAppFrame = verifierAppFrame2; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/ui/VerifierSelectionListener.java b/src/main/java/com/allatori/lib/bcel/verifier/ui/VerifierSelectionListener.java new file mode 100644 index 0000000..50eb52f --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/ui/VerifierSelectionListener.java @@ -0,0 +1,20 @@ +package com.allatori.lib.bcel.verifier.ui; + +import com.allatori.lib.bcel.verifier.VerifierAppFrame; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; + +public class VerifierSelectionListener implements ListSelectionListener { + + public final VerifierAppFrame verifierAppFrame; + + public VerifierSelectionListener(VerifierAppFrame verifierAppFrame2) { + super(); + this.verifierAppFrame = verifierAppFrame2; + } + + @Override + public void valueChanged(ListSelectionEvent listSelectionEvent) { + this.verifierAppFrame.pass3bJList_valueChanged(listSelectionEvent); + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/ui/VerifierSelectionListener2.java b/src/main/java/com/allatori/lib/bcel/verifier/ui/VerifierSelectionListener2.java new file mode 100644 index 0000000..2e50e41 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/ui/VerifierSelectionListener2.java @@ -0,0 +1,20 @@ +package com.allatori.lib.bcel.verifier.ui; + +import com.allatori.lib.bcel.verifier.VerifierAppFrame; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; + +public class VerifierSelectionListener2 implements ListSelectionListener { + + public final VerifierAppFrame verifierAppFrame; + + @Override + public void valueChanged(ListSelectionEvent listSelectionEvent) { + this.verifierAppFrame.pass3aJList_valueChanged(listSelectionEvent); + } + + public VerifierSelectionListener2(VerifierAppFrame verifierAppFrame2) { + super(); + this.verifierAppFrame = verifierAppFrame2; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/ui/VerifierSelectionListener3.java b/src/main/java/com/allatori/lib/bcel/verifier/ui/VerifierSelectionListener3.java new file mode 100644 index 0000000..89e7c86 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/ui/VerifierSelectionListener3.java @@ -0,0 +1,20 @@ +package com.allatori.lib.bcel.verifier.ui; + +import com.allatori.lib.bcel.verifier.VerifierAppFrame; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; + +public class VerifierSelectionListener3 implements ListSelectionListener { + + public final VerifierAppFrame verifierAppFrame; + + @Override + public void valueChanged(ListSelectionEvent listSelectionEvent) { + this.verifierAppFrame.classNamesJList_valueChanged(listSelectionEvent); + } + + public VerifierSelectionListener3(VerifierAppFrame verifierAppFrame2) { + super(); + this.verifierAppFrame = verifierAppFrame2; + } +} diff --git a/src/main/java/com/allatori/lib/bcel/verifier/ui/VerifierWindowListener.java b/src/main/java/com/allatori/lib/bcel/verifier/ui/VerifierWindowListener.java new file mode 100644 index 0000000..4cb0661 --- /dev/null +++ b/src/main/java/com/allatori/lib/bcel/verifier/ui/VerifierWindowListener.java @@ -0,0 +1,16 @@ +package com.allatori.lib.bcel.verifier.ui; + +import com.allatori.lib.bcel.verifier.VerifyDialog; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +public class VerifierWindowListener extends WindowAdapter { + + @Override + public void windowClosing(WindowEvent windowEvent) { + VerifyDialog.calculateCount(); + if (VerifyDialog.getClasses_to_verify() == 0) { + System.exit(0); + } + } +} diff --git a/src/main/java/com/allatori/model/ClassStorage.java b/src/main/java/com/allatori/model/ClassStorage.java new file mode 100644 index 0000000..5c6ce9e --- /dev/null +++ b/src/main/java/com/allatori/model/ClassStorage.java @@ -0,0 +1,99 @@ +package com.allatori.model; + +import com.allatori.io.ClassStorageClassLoader; +import com.allatori.lib.bcel.generic.ClassGen; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.Vector; + +public class ClassStorage { + + public Hashtable classesByName; + + public Hashtable classEntryNames; + + public Vector inputClasses; + + public ClassLoader classLoader; + + public Hashtable entryPrefixes; + + public HashSet duplicateClasses; + + public Hashtable sourceFiles; + + public void processText(ClassGen classGen, String text, String text2) { + this.processText(classGen, text); + this.classEntryNames.put("" + text + '#' + text2, classGen.getClassName()); + String text3 = "" + classGen.getClassName().replace('.', '/') + ".class"; + if (text2.endsWith(text3)) { + String text4 = text2.substring(0, text2.length() - text3.length()); + this.entryPrefixes.put("" + text + '#' + classGen.getClassName(), text4); + } + } + + public void processClassGen(ClassGen classGen) { + this.classesByName.put(classGen.getClassName(), classGen); + this.inputClasses.add(classGen); + } + + public String getText(ClassGen classGen) { + return (String) this.sourceFiles.get(classGen.getClassName()); + } + + public void processText(ClassGen classGen, String text) { + if (!"java.lang.Object".equals(classGen.getClassName())) { + if (this.classesByName.containsKey(classGen.getClassName())) { + this.duplicateClasses.add(classGen); + } else { + this.classesByName.put(classGen.getClassName(), classGen); + this.sourceFiles.put(classGen.getClassName(), text); + } + } + } + + public Vector getInputClasses() { + return this.inputClasses; + } + + public boolean matchesClassGen(ClassGen classGen) { + return this.duplicateClasses.contains(classGen); + } + + public int getClassesByName() { + return this.classesByName.size(); + } + + public ClassGen getClassGen(String text) { + return (ClassGen) this.classesByName.get(text); + } + + public ClassLoader getClassLoader() { + return this.classLoader; + } + + public Iterator getClassesByName2() { + return this.classesByName.values().iterator(); + } + + public String getText(String text) { + return (String) this.classEntryNames.get(text); + } + + public ClassStorage(ClassStorageClassLoader classStorageClassLoader) { + super(); + this.classesByName = new Hashtable(); + this.sourceFiles = new Hashtable(); + this.duplicateClasses = new HashSet(); + this.inputClasses = new Vector(); + this.classEntryNames = new Hashtable(); + this.entryPrefixes = new Hashtable(); + this.classLoader = classStorageClassLoader; + classStorageClassLoader.setClassStorage(this); + } + + public String getText2(String text) { + return (String) this.entryPrefixes.get(text); + } +} diff --git a/src/main/java/com/allatori/model/MethodContext.java b/src/main/java/com/allatori/model/MethodContext.java new file mode 100644 index 0000000..cc7e998 --- /dev/null +++ b/src/main/java/com/allatori/model/MethodContext.java @@ -0,0 +1,39 @@ +package com.allatori.model; + +import com.allatori.bytecode.MethodFactory; +import com.allatori.lib.bcel.classfile.Method; +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.lib.bcel.generic.MethodGen; + +public class MethodContext { + + public MethodGen methodGen; + + public Method method; + + public ClassGen classGen; + + public static ClassGen getClassGen(MethodContext methodContext) { + return methodContext.classGen; + } + + public MethodContext(ClassGen classGen2, Method method2) { + super(); + this.classGen = classGen2; + this.method = method2; + this.methodGen = + MethodFactory.createMethodGen( + method2, + classGen2.getClassName(), + classGen2.getConstantPool(), + classGen2.getConstantPool().getConstantPool()); + } + + public static Method getMethod(MethodContext methodContext) { + return methodContext.method; + } + + public static MethodGen getMethodGen(MethodContext methodContext) { + return methodContext.methodGen; + } +} diff --git a/src/main/java/com/allatori/model/NameMapping.java b/src/main/java/com/allatori/model/NameMapping.java new file mode 100644 index 0000000..771ebd2 --- /dev/null +++ b/src/main/java/com/allatori/model/NameMapping.java @@ -0,0 +1,14 @@ +package com.allatori.model; + +public class NameMapping { + + public String text; + + public String text2; + + public NameMapping(String text, String text2) { + super(); + this.text = text; + this.text2 = text2; + } +} diff --git a/src/main/java/com/allatori/naming/ClassNameTable.java b/src/main/java/com/allatori/naming/ClassNameTable.java new file mode 100644 index 0000000..4983c09 --- /dev/null +++ b/src/main/java/com/allatori/naming/ClassNameTable.java @@ -0,0 +1,42 @@ +package com.allatori.naming; + +import com.allatori.config.Configuration; +import com.allatori.naming.generator.NameGenerator; +import com.allatori.util.LookupTable; + +public class ClassNameTable { + + public NameGenerator nameGenerator; + + public LookupTable lookupTable; + + public final NamingContext namingContext; + + public LookupTable lookupTable2; + + public static NameGenerator getNameGenerator(ClassNameTable classNameTable) { + return classNameTable.nameGenerator; + } + + public ClassNameTable(NamingContext namingContext2) { + super(); + this.namingContext = namingContext2; + this.nameGenerator = + Configuration.getRenamingOptions().getNameGenerationOptions().createNameGenerator4(); + this.lookupTable = new LookupTable(); + this.lookupTable2 = new LookupTable(); + } + + public static LookupTable getLookupTable(ClassNameTable classNameTable) { + return classNameTable.lookupTable2; + } + + public static LookupTable getLookupTable2(ClassNameTable classNameTable) { + return classNameTable.lookupTable; + } + + public ClassNameTable( + NamingContext namingContext, NamingConstructorToken namingConstructorToken) { + this(namingContext); + } +} diff --git a/src/main/java/com/allatori/naming/FieldNameTable.java b/src/main/java/com/allatori/naming/FieldNameTable.java new file mode 100644 index 0000000..defd250 --- /dev/null +++ b/src/main/java/com/allatori/naming/FieldNameTable.java @@ -0,0 +1,49 @@ +package com.allatori.naming; + +import com.allatori.config.Configuration; +import com.allatori.naming.generator.NameGenerator; +import com.allatori.util.LookupTable; + +public class FieldNameTable { + + public final NamingContext namingContext; + + public LookupTable lookupTable; + + public NameGenerator nameGenerator; + + public LookupTable lookupTable2; + + public LookupTable lookupTable3; + + public static LookupTable getLookupTable(FieldNameTable fieldNameTable) { + return fieldNameTable.lookupTable2; + } + + public static LookupTable getLookupTable2(FieldNameTable fieldNameTable) { + return fieldNameTable.lookupTable3; + } + + public static NameGenerator getNameGenerator(FieldNameTable fieldNameTable) { + return fieldNameTable.nameGenerator; + } + + public FieldNameTable(NamingContext namingContext2) { + super(); + this.namingContext = namingContext2; + this.nameGenerator = + Configuration.getRenamingOptions().getNameGenerationOptions().createNameGenerator5(); + this.lookupTable2 = new LookupTable(); + this.lookupTable = new LookupTable(); + this.lookupTable3 = new LookupTable(); + } + + public FieldNameTable( + NamingContext namingContext, NamingConstructorToken namingConstructorToken) { + this(namingContext); + } + + public static LookupTable getLookupTable3(FieldNameTable fieldNameTable) { + return fieldNameTable.lookupTable; + } +} diff --git a/src/main/java/com/allatori/naming/MappingImportHandler.java b/src/main/java/com/allatori/naming/MappingImportHandler.java new file mode 100644 index 0000000..8b703ab --- /dev/null +++ b/src/main/java/com/allatori/naming/MappingImportHandler.java @@ -0,0 +1,353 @@ +package com.allatori.naming; + +import com.allatori.config.Configuration; +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.util.LookupTable; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; +import java.util.Iterator; +import java.util.Set; +import java.util.Vector; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.DefaultHandler; + +public class MappingImportHandler extends DefaultHandler { + + public LookupTable lookupTable; + + public String text; + + public String text2; + + public String text3; + + public String text4; + + public String text5; + + public final NameRenamer nameRenamer; + + public String text6; + + public String text7; + + public String text8; + + public String text9; + + public String text10; + + public String text11; + + public String text12; + + public String text13; + + public String text14; + + public String text15; + + @Override + public void startElement(String text16, String text17, String text18, Attributes attributes) { + if (this.text15.equals(text18)) { + this.text11 = attributes.getValue(this.text8); + this.text14 = attributes.getValue(this.text); + if (NameRenamer.isEnabled()) { + String text22 = NameUtils.getText2(this.text14); + if (NameRenamer.getLookupTable().matchesText(text22)) { + this.text14 = + NameRenamer.getLookupTable().getText(text22) + this.text14.substring(text22.length()); + } + } + ParameterNameTable.getLookupTable( + NamingContext.getParameterNameTable(NameRenamer.getNamingContext(this.nameRenamer))) + .processText(this.text11, this.text14); + ParameterNameTable.getLookupTable3( + NamingContext.getParameterNameTable(NameRenamer.getNamingContext(this.nameRenamer))) + .processText(this.text14, this.text11); + this.update3(); + } else { + if (this.text7.equals(text18)) { + String value = attributes.getValue(this.text8); + String value2 = attributes.getValue(this.text); + String text19 = value.substring(0, value.indexOf("(")); + String text20 = value.substring(value.indexOf("(")); + MethodNameTable.getLookupTable2( + NamingContext.getMethodNameTable(NameRenamer.getNamingContext(this.nameRenamer))) + .processText("" + this.text11 + "&" + text19 + "&" + text20, value2); + String text21 = "" + this.text11 + "&" + value2 + "&" + NameUtils.getText(text20); + if (MethodNameTable.getLookupTable3( + NamingContext.getMethodNameTable(NameRenamer.getNamingContext(this.nameRenamer))) + .matchesText(text21)) { + this.lookupTable.processText(text21, this.text11); + } + MethodNameTable.getLookupTable3( + NamingContext.getMethodNameTable(NameRenamer.getNamingContext(this.nameRenamer))) + .processText(text21, "&"); + if (Configuration.getRenamingOptions().isEnabled8() && !value2.equals(text19)) { + MethodNameTable.getLookupTable4( + NamingContext.getMethodNameTable(NameRenamer.getNamingContext(this.nameRenamer))) + .processText("" + text19 + "&" + NameUtils.getText(text20), value2); + return; + } + } else { + if (this.text3.equals(text18)) { + String value3 = attributes.getValue(this.text8); + String value4 = attributes.getValue(this.text); + String text23 = value3.substring(0, value3.indexOf(this.text12)); + String text24 = value3.substring(value3.indexOf(this.text12) + 1); + FieldNameTable.getLookupTable( + NamingContext.getFieldNameTable(NameRenamer.getNamingContext(this.nameRenamer))) + .processText("" + this.text11 + "&" + text23 + "&" + text24, value4); + FieldNameTable.getLookupTable3( + NamingContext.getFieldNameTable(NameRenamer.getNamingContext(this.nameRenamer))) + .processText("" + this.text11 + "&" + value4 + "&" + text24, "&"); + return; + } + if (this.text2.equals(text18)) { + String value5 = attributes.getValue(this.text8); + String value6 = attributes.getValue(this.text); + NameRenamer.getNameMappingEntry(this.nameRenamer).processText(value5, value6); + return; + } + if (this.text4.equals(text18)) { + Integer value7 = Integer.valueOf(attributes.getValue(this.text10)); + NameRenamer.getNameMappingEntry(this.nameRenamer).getValues().add(value7); + return; + } + if (this.text13.equals(text18)) { + String value8 = attributes.getValue(this.text6); + String value9 = attributes.getValue(this.text9); + String value10 = attributes.getValue(this.text5); + MethodNameTable.getLookupTable5( + NamingContext.getMethodNameTable(NameRenamer.getNamingContext(this.nameRenamer))) + .processText("" + value8 + "&" + value9, value10); + } + } + } + } + + public void update() { + try { + Vector vector = new Vector(this.lookupTable.getEntries2()); + int value; + for (int value2 = value = 0; value2 < vector.size(); value2 = ++value) { + String text = (String) vector.get(value); + String text2 = this.lookupTable.getText(text); + ClassGen classGen; + if ((classGen = NameRenamer.getClassStorage(this.nameRenamer).getClassGen(text2)) != null) { + String[] interfaceNames = classGen.getInterfaceNames(); + int value3; + for (int value4 = value3 = 0; value4 < interfaceNames.length; value4 = value3) { + String text3 = interfaceNames[value3]; + LookupTable lookupTable2 = this.lookupTable; + StringBuilder stringBuilder = + new StringBuilder().insert(0, text3).append(text.substring(text.indexOf("&"))); + value3++; + lookupTable2.processText(stringBuilder.toString(), text3); + } + } + } + Set entries2 = this.lookupTable.getEntries2(); + Vector vector2 = + new Vector( + MethodNameTable.getLookupTable2( + NamingContext.getMethodNameTable( + NameRenamer.getNamingContext(this.nameRenamer))) + .getEntries2()); + for (String text4 : ((Iterable) ((Iterable) entries2))) { + String text5 = this.lookupTable.getText(text4); + Iterator iterator2 = vector2.iterator(); + while (iterator2.hasNext()) { + String text6; + if ((text6 = (String) iterator2.next()).startsWith(text5)) { + String text7 = + MethodNameTable.getLookupTable2( + NamingContext.getMethodNameTable( + NameRenamer.getNamingContext(this.nameRenamer))) + .getText(text6); + if (text4.substring(text4.indexOf("&") + 1, text4.lastIndexOf("&")).equals(text7)) { + String text8 = text4.substring(text4.lastIndexOf("&") + 1); + String text9 = text6.substring(text6.lastIndexOf("&") + 1); + if (text8.equals(NameUtils.getText(text9))) { + MethodNameTable.getLookupTable2( + NamingContext.getMethodNameTable( + NameRenamer.getNamingContext(this.nameRenamer))) + .processText(text6); + MethodNameTable.getLookupTable3( + NamingContext.getMethodNameTable( + NameRenamer.getNamingContext(this.nameRenamer))) + .processText(text4); + } + } + } + } + } + } catch (Exception exception) { + } + } + + public String createText(String text, LookupTable lookupTable) { + String text2 = ""; + while (text.length() > 0) { + int value = text.indexOf(76); + int value2 = text.indexOf(59); + if (value != -1 && value2 != -1 && value < value2) { + String text3 = text.substring(value + 1, value2).replace('/', '.'); + if (lookupTable.getText(text3) != null) { + text3 = lookupTable.getText(text3); + } + String text4 = text3.replace('.', '/'); + text2 = "" + text2 + text.substring(0, value + 1) + text4 + ";"; + text = text.substring(value2 + 1); + } else { + text2 = "" + text2 + text; + text = ""; + } + } + return text2; + } + + public static void processMappingImportHandler(MappingImportHandler mappingImportHandler) + throws ParserConfigurationException, + SAXException, + FileNotFoundException, + UnsupportedEncodingException, + IOException { + mappingImportHandler.update4(); + } + + public void update2() { + for (String text : + ((Iterable) + ((Iterable) + FieldNameTable.getLookupTable( + NamingContext.getFieldNameTable( + NameRenamer.getNamingContext(this.nameRenamer))) + .getEntries2()))) { + String text2; + String text3 = + this.createText( + text2 = text.substring(text.lastIndexOf("&") + 1), + ParameterNameTable.getLookupTable( + NamingContext.getParameterNameTable( + NameRenamer.getNamingContext(this.nameRenamer)))); + if (!text2.equals(text3)) { + FieldNameTable.getLookupTable2( + NamingContext.getFieldNameTable(NameRenamer.getNamingContext(this.nameRenamer))) + .processText(text2, text3); + } + } + for (String text4 : + ((Iterable) + ((Iterable) + MethodNameTable.getLookupTable2( + NamingContext.getMethodNameTable( + NameRenamer.getNamingContext(this.nameRenamer))) + .getEntries2()))) { + String text5; + String text6 = + this.createText( + text5 = text4.substring(text4.lastIndexOf("&") + 1), + ParameterNameTable.getLookupTable( + NamingContext.getParameterNameTable( + NameRenamer.getNamingContext(this.nameRenamer)))); + if (!text5.equals(text6)) { + MethodNameTable.getLookupTable( + NamingContext.getMethodNameTable(NameRenamer.getNamingContext(this.nameRenamer))) + .processText(text5, text6); + } + } + } + + public MappingImportHandler(NameRenamer nameRenamer2) { + super(); + this.nameRenamer = nameRenamer2; + this.lookupTable = new LookupTable(); + this.text8 = "old"; + this.text = "new"; + this.text15 = "class"; + this.text7 = "method"; + this.text3 = "field"; + this.text2 = "source"; + this.text4 = "line"; + this.text10 = "l"; + this.text13 = "annotation"; + this.text6 = "oldClassName"; + this.text9 = "oldMethodName"; + this.text5 = "newMethodName"; + this.text12 = " "; + } + + public void update3() { + String text2 = NameUtils.getText2(this.text11); + String text22 = NameUtils.getText2(this.text14); + if (!Configuration.getRenamingOptions().isText() + || !Configuration.getRenamingOptions().getDefaultPackage().equals(text22)) { + int value = 0; + int value2; + for (int value3 = value2 = text2.length() - 1; value3 > 0; value3 = --value2) { + if (text2.charAt(value2) == '.') { + value++; + } + } + int value4; + for (int value5 = value4 = text22.length() - 1; value5 > 0; value5 = --value4) { + if (text22.charAt(value4) == '.') { + value--; + } + } + if (value == 0) { + ClassNameTable.getLookupTable2( + NamingContext.getClassNameTable(NameRenamer.getNamingContext(this.nameRenamer))) + .processText(text2, text22); + ClassNameTable.getLookupTable( + NamingContext.getClassNameTable(NameRenamer.getNamingContext(this.nameRenamer))) + .processText(text22, "&"); + String text = text2; + while (text.lastIndexOf(46) > 0) { + text2 = text2.substring(0, text2.lastIndexOf(46)); + text22 = text22.substring(0, text22.lastIndexOf(46)); + LookupTable lookupTable2 = + ClassNameTable.getLookupTable2( + NamingContext.getClassNameTable(NameRenamer.getNamingContext(this.nameRenamer))); + text = text2; + lookupTable2.processText(text2, text22); + ClassNameTable.getLookupTable( + NamingContext.getClassNameTable(NameRenamer.getNamingContext(this.nameRenamer))) + .processText(text22, "&"); + } + } + } + } + + public MappingImportHandler( + NameRenamer nameRenamer, NamingConstructorToken namingConstructorToken) { + this(nameRenamer); + } + + public void update4() + throws ParserConfigurationException, + SAXException, + FileNotFoundException, + UnsupportedEncodingException, + IOException { + XMLReader xMLReader = SAXParserFactory.newInstance().newSAXParser().getXMLReader(); + xMLReader.setContentHandler(this); + xMLReader.parse( + new InputSource( + new InputStreamReader( + new FileInputStream(Configuration.getRenamingOptions().getIncrementalObfuscation()), + "UTF-8"))); + this.update2(); + this.update(); + } +} diff --git a/src/main/java/com/allatori/naming/MappingXmlWriter.java b/src/main/java/com/allatori/naming/MappingXmlWriter.java new file mode 100644 index 0000000..7b1d898 --- /dev/null +++ b/src/main/java/com/allatori/naming/MappingXmlWriter.java @@ -0,0 +1,285 @@ +package com.allatori.naming; + +import com.allatori.VersionInfo; +import com.allatori.config.Configuration; +import com.allatori.model.NameMapping; +import com.allatori.optimizer.OptimizationStatistics; +import com.allatori.util.Log; +import java.io.BufferedWriter; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.util.Calendar; +import java.util.Collections; +import java.util.Vector; + +public class MappingXmlWriter { + + public static StringBuilder stringBuilder = new StringBuilder(4096); + + public static void processPrintWriter(PrintWriter printWriter) { + printWriter.println("\n"); + printWriter.println( + "\n"); + if (stringBuilder.length() > 0) { + printWriter.println( + new StringBuilder().insert(0, "\n").toString()); + } + printWriter.println( + "\n"); + printWriter.println(""); + } + + public static int calculateCount(Vector vector, String text) { + int value = 0; + int value2 = vector.size() - 1; + while (value <= value2) { + int value3 = value + value2 >> 1; + int value4; + if ((value4 = ((Comparable) vector.get(value3)).compareTo(text)) < 0) { + value = value3 + 1; + } else { + if (value4 <= 0) { + return value3; + } + value2 = value3 - 1; + } + } + return value; + } + + public static void processRenamingLog(PrintWriter printWriter, RenamingLog renamingLog) { + printWriter.println(" "); + Vector vector = new Vector(renamingLog.lookupTable4.getEntries2()); + Vector vector2 = new Vector(renamingLog.lookupTable5.getEntries2()); + Vector vector3 = new Vector(renamingLog.lookupTable2.getEntries2()); + Collections.sort(vector2); + Collections.sort(vector3); + String text3 = "\" new=\""; + String text4 = "\"/>"; + String text5 = ""; + String text6 = ""; + String text7 = " = 0; value2 = value) { + String text8 = (String) vector.get(value); + printWriter.println( + (String) " "); + String text9 = "" + text8 + "&"; + int value3; + value2 = value3 = calculateCount(vector2, text9); + String text10; + while (value2 < vector2.size() && (text10 = (String) vector2.get(value3)).startsWith(text9)) { + String text11 = text10.substring(text10.indexOf("&") + 1, text10.lastIndexOf("&")); + if (!text5.equals(text11) && !text6.equals(text11)) { + String text12 = text10.substring(text10.lastIndexOf("&") + 1); + Vector vector4; + if (renamingLog.lookupTable3.matchesText(text10)) { + vector4 = vector2; + printWriter.println( + "" + + text7 + + text11 + + text12 + + text3 + + renamingLog.lookupTable5.getText(text10) + + renamingLog.lookupTable3.getText(text10) + + text4); + renamingLog.lookupTable3.processText(text10); + } else { + printWriter.println( + "" + + text7 + + text11 + + text12 + + text3 + + renamingLog.lookupTable5.getText(text10) + + text4); + vector4 = vector2; + } + vector4.remove(value3); + value2 = value3; + } else { + vector2.remove(value3); + value2 = value3; + } + } + int value4; + value2 = value4 = calculateCount(vector3, text9); + String text13; + while (value2 < vector3.size() && (text13 = (String) vector3.get(value4)).startsWith(text9)) { + String text14 = text13.substring(text13.indexOf("&") + 1, text13.lastIndexOf("&")); + String text15 = text13.substring(text13.lastIndexOf("&") + 1); + value2 = value4; + printWriter.println( + "" + + ((String) " "); + } + Vector vector5; + if ((vector5 = new Vector(renamingLog.lookupTable.getEntries2())).size() > 0) { + printWriter.println((String) " "); + int value5; + for (int value6 = value5 = vector5.size() - 1; value6 >= 0; value6 = --value5) { + String text16 = (String) vector5.get(value5); + String text17 = renamingLog.lookupTable.getText(text16); + String text18 = text16.substring(text16.indexOf("&") + 1); + String text19 = text16.substring(0, text16.indexOf("&")); + if (!text5.equals(text18) && !text6.equals(text18)) { + printWriter.println( + "" + + ((String) " "); + } + printWriter.println(" "); + int value7; + for (int value8 = value7 = renamingLog.values2.size() - 1; value8 >= 0; value8 = value7) { + NameMapping nameMapping = (NameMapping) renamingLog.values2.get(value7); + StringBuilder stringBuilder = + new StringBuilder() + .insert(0, (String) " "); + printWriter.println(" "); + int value9; + for (int value10 = value9 = 0; value10 < renamingLog.values.size(); value10 = value9) { + StringBuilder stringBuilder2 = + new StringBuilder() + .insert(0, (String) " "); + printWriter.println(" "); + } + + public static void update() { + String text; + if ((text = Configuration.getOutputOptions().getLogFile()) == null) { + Log.warn("Log file is not set."); + stringBuilder.delete(0, stringBuilder.length()); + } else { + PrintWriter printWriter = null; + label90: + { + label91: + { + try { + try { + FileOutputStream fileOutputStream = new FileOutputStream(text); + PrintWriter printWriter2 = + printWriter = + new PrintWriter( + new BufferedWriter( + new OutputStreamWriter(fileOutputStream, "UTF-8"), 524288)); + processPrintWriter(printWriter2); + processRenamingLog(printWriter2, Configuration.getMappingOptions().renamingLog); + processPrintWriter2(printWriter2); + printWriter2.flush(); + break label90; + } catch (FileNotFoundException fileNotFoundException) { + Log.error("Cannot write log to '" + text + "' file."); + } catch (Exception exception) { + Log.error("Writing log file failed with exception: " + exception.getMessage()); + break label91; + } + } catch (Throwable throwable) { + stringBuilder.delete(0, stringBuilder.length()); + try { + printWriter.close(); + } catch (Exception exception2) { + throw throwable; + } + throw throwable; + } + stringBuilder.delete(0, stringBuilder.length()); + try { + printWriter.close(); + return; + } catch (Exception exception3) { + return; + } + } + stringBuilder.delete(0, stringBuilder.length()); + try { + printWriter.close(); + return; + } catch (Exception exception4) { + return; + } + } + stringBuilder.delete(0, stringBuilder.length()); + try { + printWriter.close(); + } catch (Exception exception5) { + } + } + } + + public static void processPrintWriter2(PrintWriter printWriter) { + printWriter.println(""); + } +} diff --git a/src/main/java/com/allatori/naming/MethodNameTable.java b/src/main/java/com/allatori/naming/MethodNameTable.java new file mode 100644 index 0000000..79c5f67 --- /dev/null +++ b/src/main/java/com/allatori/naming/MethodNameTable.java @@ -0,0 +1,63 @@ +package com.allatori.naming; + +import com.allatori.config.Configuration; +import com.allatori.naming.generator.NameGenerator; +import com.allatori.util.LookupTable; + +public class MethodNameTable { + + public LookupTable lookupTable; + + public LookupTable lookupTable2; + + public NameGenerator nameGenerator; + + public LookupTable lookupTable3; + + public final NamingContext namingContext; + + public LookupTable lookupTable4; + + public LookupTable lookupTable5; + + public static LookupTable getLookupTable(MethodNameTable methodNameTable) { + return methodNameTable.lookupTable; + } + + public static LookupTable getLookupTable2(MethodNameTable methodNameTable) { + return methodNameTable.lookupTable3; + } + + public MethodNameTable(NamingContext namingContext2) { + super(); + this.namingContext = namingContext2; + this.nameGenerator = + Configuration.getRenamingOptions().getNameGenerationOptions().createNameGenerator2(); + this.lookupTable3 = new LookupTable(); + this.lookupTable4 = new LookupTable(); + this.lookupTable5 = new LookupTable(); + this.lookupTable = new LookupTable(); + this.lookupTable2 = new LookupTable(); + } + + public static LookupTable getLookupTable3(MethodNameTable methodNameTable) { + return methodNameTable.lookupTable5; + } + + public static NameGenerator getNameGenerator(MethodNameTable methodNameTable) { + return methodNameTable.nameGenerator; + } + + public static LookupTable getLookupTable4(MethodNameTable methodNameTable) { + return methodNameTable.lookupTable2; + } + + public MethodNameTable( + NamingContext namingContext, NamingConstructorToken namingConstructorToken) { + this(namingContext); + } + + public static LookupTable getLookupTable5(MethodNameTable methodNameTable) { + return methodNameTable.lookupTable4; + } +} diff --git a/src/main/java/com/allatori/naming/NameComparator.java b/src/main/java/com/allatori/naming/NameComparator.java new file mode 100644 index 0000000..5b49835 --- /dev/null +++ b/src/main/java/com/allatori/naming/NameComparator.java @@ -0,0 +1,13 @@ +package com.allatori.naming; + +import java.util.Comparator; + +public class NameComparator implements Comparator { + + @Override + public int compare(Object result, Object result2) { + String text = (String) result; + String text2 = (String) result2; + return text.length() - text2.length(); + } +} diff --git a/src/main/java/com/allatori/naming/NameLengthComparator.java b/src/main/java/com/allatori/naming/NameLengthComparator.java new file mode 100644 index 0000000..c5b2e83 --- /dev/null +++ b/src/main/java/com/allatori/naming/NameLengthComparator.java @@ -0,0 +1,13 @@ +package com.allatori.naming; + +import java.util.Comparator; + +public class NameLengthComparator implements Comparator { + + @Override + public int compare(Object result, Object result2) { + String text = (String) result; + String text2 = (String) result2; + return text.length() - text2.length(); + } +} diff --git a/src/main/java/com/allatori/naming/NameMappingEntry.java b/src/main/java/com/allatori/naming/NameMappingEntry.java new file mode 100644 index 0000000..b47d63e --- /dev/null +++ b/src/main/java/com/allatori/naming/NameMappingEntry.java @@ -0,0 +1,170 @@ +package com.allatori.naming; + +import com.allatori.config.Configuration; +import com.allatori.lib.bcel.classfile.Attribute; +import com.allatori.lib.bcel.classfile.SourceFile; +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.lib.bcel.generic.LineNumberGen; +import com.allatori.lib.bcel.generic.MethodGen; +import com.allatori.model.NameMapping; +import com.allatori.naming.generator.NameGenerator; +import com.allatori.util.LookupTable; +import com.allatori.util.random.RandomUtils; +import java.util.HashSet; +import java.util.Vector; + +public class NameMappingEntry { + + public Vector values; + + public NameGenerator nameGenerator; + + public String text; + + public LookupTable lookupTable; + + public Vector values2; + + public LookupTable lookupTable2; + + public String text2; + + public HashSet values3; + + public Vector getValues2() { + return this.values2; + } + + public void processClassGen(ClassGen classGen) { + int lineNumbersMode = + Configuration.getRenamingOptions().getLineNumberOptions().getLineNumbersMode(); + Configuration.getRenamingOptions().getLineNumberOptions(); + if (lineNumbersMode != 2) { + lineNumbersMode = + Configuration.getRenamingOptions().getLineNumberOptions().getLineNumbersMode(); + Configuration.getRenamingOptions().getLineNumberOptions(); + int value; + if (lineNumbersMode == 3) { + Attribute[] attributes; + for (int value2 = value = (attributes = classGen.getAttributes()).length - 1; + value2 >= 0; + value2 = --value) { + Attribute attribute; + if ((attribute = attributes[value]) instanceof SourceFile) { + classGen.processAttribute2(attribute); + return; + } + } + } else { + lineNumbersMode = + Configuration.getRenamingOptions().getLineNumberOptions().getLineNumbersMode(); + Configuration.getRenamingOptions().getLineNumberOptions(); + int value3; + if (lineNumbersMode == 1) { + Attribute[] attributes2; + for (int value4 = value3 = (attributes2 = classGen.getAttributes()).length - 1; + value4 >= 0; + value4 = --value3) { + Attribute attribute2; + if ((attribute2 = attributes2[value3]) instanceof SourceFile) { + SourceFile sourceFile; + String text = (sourceFile = (SourceFile) attribute2).getText(); + String text2; + if ((text2 = this.lookupTable.getText(text)) == null) { + do { + text2 = this.nameGenerator.nextName(); + } while (this.values3.contains(text2)); + this.values2.add(new NameMapping(text, text2)); + this.lookupTable.processText(text, text2); + this.values3.add(text2); + } + sourceFile.setSourceFileIndex(classGen.getConstantPool().addUtf8(text2)); + return; + } + } + } + } + } + } + + public Vector getValues() { + return this.values; + } + + public NameMappingEntry() { + super(); + this.nameGenerator = + Configuration.getRenamingOptions().getNameGenerationOptions().createNameGenerator(); + this.values2 = new Vector(); + this.lookupTable = new LookupTable(); + this.values3 = new HashSet(); + this.values = new Vector(); + this.lookupTable2 = new LookupTable(); + this.text2 = "\" s=\""; + this.text = "\" e=\""; + } + + public LookupTable getLookupTable2() { + return this.lookupTable2; + } + + public void processMethodGen(String text3, MethodGen methodGen) { + int lineNumbersMode = + Configuration.getRenamingOptions().getLineNumberOptions().getLineNumbersMode(); + Configuration.getRenamingOptions().getLineNumberOptions(); + if (lineNumbersMode != 2) { + lineNumbersMode = + Configuration.getRenamingOptions().getLineNumberOptions().getLineNumbersMode(); + Configuration.getRenamingOptions().getLineNumberOptions(); + if (lineNumbersMode == 3) { + methodGen.removeLineNumbers(); + } else { + lineNumbersMode = + Configuration.getRenamingOptions().getLineNumberOptions().getLineNumbersMode(); + Configuration.getRenamingOptions().getLineNumberOptions(); + if (lineNumbersMode == 1) { + LineNumberGen[] lineNumbers = methodGen.getLineNumbers(); + int value = Integer.MAX_VALUE; + int value2 = Integer.MIN_VALUE; + int value3; + for (int value4 = value3 = lineNumbers.length - 1; value4 >= 0; value4 = value3) { + LineNumberGen lineNumberGen; + int value5; + if ((value5 = (lineNumberGen = lineNumbers[value3]).getSourceLine()) < value) { + value = value5; + } + if (value5 > value2) { + value2 = value5; + } + if (value5 > this.values.size() - 1) { + int size2 = this.values.size(); + int value6 = value5 - size2 + 200; + Vector vector = new Vector(value6); + int value7; + for (int value8 = value7 = 0; value8 < value6; value8 = value7) { + vector.add(new Integer(size2 + value7++)); + } + RandomUtils.processValues(vector); + this.values.addAll(vector); + } + Object result = this.values.get(value5); + LineNumberGen lineNumberGen2 = lineNumberGen; + value3--; + lineNumberGen2.setSourceLine((Integer) result); + } + if (value < Integer.MAX_VALUE) { + this.lookupTable2.processText( + "" + text3 + "&" + methodGen.getName() + "&" + methodGen.getText(), + "" + this.text2 + value + this.text + value2); + } + } + } + } + } + + public void processText(String text, String text2) { + this.values2.add(new NameMapping(text, text2)); + this.lookupTable.processText(text, text2); + this.values3.add(text2); + } +} diff --git a/src/main/java/com/allatori/naming/NameRenamer.java b/src/main/java/com/allatori/naming/NameRenamer.java new file mode 100644 index 0000000..367a8fc --- /dev/null +++ b/src/main/java/com/allatori/naming/NameRenamer.java @@ -0,0 +1,1793 @@ +package com.allatori.naming; + +import com.allatori.bytecode.ClassHierarchy; +import com.allatori.bytecode.MethodFactory; +import com.allatori.config.Configuration; +import com.allatori.engine.ObfuscationAbortException; +import com.allatori.lib.bcel.classfile.Attribute; +import com.allatori.lib.bcel.classfile.BootstrapMethods; +import com.allatori.lib.bcel.classfile.Code; +import com.allatori.lib.bcel.classfile.Constant; +import com.allatori.lib.bcel.classfile.ConstantCP; +import com.allatori.lib.bcel.classfile.ConstantClass; +import com.allatori.lib.bcel.classfile.ConstantFieldref; +import com.allatori.lib.bcel.classfile.ConstantInterfaceMethodref; +import com.allatori.lib.bcel.classfile.ConstantInvokeDynamic; +import com.allatori.lib.bcel.classfile.ConstantMethodType; +import com.allatori.lib.bcel.classfile.ConstantMethodref; +import com.allatori.lib.bcel.classfile.ConstantNameAndType; +import com.allatori.lib.bcel.classfile.ConstantPool; +import com.allatori.lib.bcel.classfile.ConstantUtf8; +import com.allatori.lib.bcel.classfile.ConstantValue; +import com.allatori.lib.bcel.classfile.Deprecated; +import com.allatori.lib.bcel.classfile.EnclosingMethod; +import com.allatori.lib.bcel.classfile.ExceptionTable; +import com.allatori.lib.bcel.classfile.Field; +import com.allatori.lib.bcel.classfile.InnerClass; +import com.allatori.lib.bcel.classfile.InnerClasses; +import com.allatori.lib.bcel.classfile.LineNumberTable; +import com.allatori.lib.bcel.classfile.LocalVariableTable; +import com.allatori.lib.bcel.classfile.Method; +import com.allatori.lib.bcel.classfile.NestHost; +import com.allatori.lib.bcel.classfile.NestMembers; +import com.allatori.lib.bcel.classfile.PMGClass; +import com.allatori.lib.bcel.classfile.Signature; +import com.allatori.lib.bcel.classfile.SourceFile; +import com.allatori.lib.bcel.classfile.StackMap; +import com.allatori.lib.bcel.classfile.Synthetic; +import com.allatori.lib.bcel.classfile.Unknown; +import com.allatori.lib.bcel.generic.AnnotationElementValueGen; +import com.allatori.lib.bcel.generic.AnnotationEntryGen; +import com.allatori.lib.bcel.generic.ArrayElementValueGen; +import com.allatori.lib.bcel.generic.ClassElementValueGen; +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.lib.bcel.generic.ConstantPoolGen; +import com.allatori.lib.bcel.generic.ElementValueGen; +import com.allatori.lib.bcel.generic.ElementValuePairGen; +import com.allatori.lib.bcel.generic.EnumElementValueGen; +import com.allatori.lib.bcel.generic.FieldGen; +import com.allatori.lib.bcel.generic.LocalVariableGen; +import com.allatori.lib.bcel.generic.MethodGen; +import com.allatori.lib.bcel.generic.SimpleElementValueGen; +import com.allatori.lib.bcel.generic.Type; +import com.allatori.model.ClassStorage; +import com.allatori.naming.generator.LowercaseNameGenerator; +import com.allatori.naming.generator.MainNameGenerator; +import com.allatori.util.Log; +import com.allatori.util.LookupTable; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.StringTokenizer; +import java.util.Vector; + +public class NameRenamer { + + public ClassHierarchy classHierarchy; + + public static final String TEXT = "&"; + + public static boolean enabled = false; + + public static LookupTable lookupTable = new LookupTable(); + + public NamingContext namingContext = new NamingContext(this, null); + + public ClassStorage classStorage; + + public NameMappingEntry nameMappingEntry = new NameMappingEntry(); + + public static NameMappingEntry getNameMappingEntry(NameRenamer nameRenamer) { + return nameRenamer.nameMappingEntry; + } + + public void update() throws ObfuscationAbortException { + MainNameGenerator.reset2(); + Iterator iterator2; + Iterator iterator3 = iterator2 = this.classHierarchy.getValues().iterator(); + while (iterator3.hasNext()) { + ClassGen classGen = (ClassGen) iterator2.next(); + if (Configuration.getIgnoreClassesOptions().matchesClassGen(this.classStorage, classGen)) { + iterator3 = iterator2; + } else { + this.processClassGen9(classGen); + this.processClassGen8(classGen); + this.processClassGen7(classGen); + iterator3 = iterator2; + } + } + if (!enabled && lookupTable.getEntries() > 0) { + enabled = true; + throw new ObfuscationAbortException(); + } + } + + public void update2() { + Iterator iterator2; + Iterator iterator3 = iterator2 = this.classHierarchy.getValues().iterator(); + while (iterator3.hasNext()) { + ClassGen classGen = (ClassGen) iterator2.next(); + if (Configuration.getIgnoreClassesOptions().matchesClassGen(this.classStorage, classGen)) { + iterator3 = iterator2; + } else { + this.processClassGen4(classGen); + this.processClassGen5(classGen); + iterator3 = iterator2; + } + } + } + + public NameRenamer(ClassStorage classStorage2) { + this.classStorage = classStorage2; + NameRenamer nameRenamer; + if (Configuration.getRenamingOptions().isText2()) { + try { + MappingImportHandler.processMappingImportHandler(new MappingImportHandler(this, null)); + } catch (Exception exception) { + throw new RuntimeException(exception); + } + nameRenamer = this; + } else { + nameRenamer = this; + } + nameRenamer.classHierarchy = new ClassHierarchy(classStorage2); + } + + public boolean matchesEnabled(ClassGen classGen, String text, String text2, boolean matches) { + if (FieldNameTable.getLookupTable3(NamingContext.getFieldNameTable(this.namingContext)) + .matchesText("" + classGen.getClassName() + "&" + text + "&" + text2)) { + return true; + } + if (!matches) { + return false; + } + int value; + Vector vector; + for (int value2 = + value = (vector = this.classHierarchy.getValues(classGen.getClassName())).size() - 1; + value2 >= 0; + value2 = --value) { + if (this.matchesEnabled((ClassGen) vector.get(value), text, text2, matches)) { + return true; + } + } + return false; + } + + public void processClassGen(ClassGen classGen) { + int value; + ConstantPoolGen constantPoolGen; + for (int value2 = value = (constantPoolGen = classGen.getConstantPool()).getSize() - 1; + value2 >= 0; + value2 = --value) { + Constant constant; + if (!((constant = constantPoolGen.getConstant(value)) instanceof ConstantClass)) { + if (constant instanceof ConstantCP) { + ConstantPool constantPool = constantPoolGen.getConstantPool(); + ConstantCP constantCP; + String classValue = (constantCP = (ConstantCP) constant).getClass(constantPool); + String text; + if ((text = + ParameterNameTable.getLookupTable3( + NamingContext.getParameterNameTable(this.namingContext)) + .getText(classValue)) + != null) { + classValue = text; + } + ConstantNameAndType constantNameAndType = + (ConstantNameAndType) + constantPoolGen.getConstant(constantCP.getName_and_type_index()); + String text2 = constantNameAndType.getText(constantPool); + String text22 = constantNameAndType.getText2(constantPool); + String text3 = null; + String text4 = null; + String text5; + if (!(constantCP instanceof ConstantMethodref) + && !(constantCP instanceof ConstantInterfaceMethodref)) { + if (constantCP instanceof ConstantFieldref) { + text3 = + FieldNameTable.getLookupTable(NamingContext.getFieldNameTable(this.namingContext)) + .getText("" + classValue + "&" + text2 + "&" + text22); + text4 = + FieldNameTable.getLookupTable2( + NamingContext.getFieldNameTable(this.namingContext)) + .getText(text22); + } + text5 = text3; + } else { + text3 = + MethodNameTable.getLookupTable2( + NamingContext.getMethodNameTable(this.namingContext)) + .getText("" + classValue + "&" + text2 + "&" + text22); + text4 = + MethodNameTable.getLookupTable(NamingContext.getMethodNameTable(this.namingContext)) + .getText(text22); + text5 = text3; + } + if (text5 != null && !text3.equals(text2) || text4 != null) { + if (text3 == null) { + text3 = text2; + } + if (text4 == null) { + text4 = text22; + } + int value3 = constantPoolGen.addNameAndType(text3, text4); + constantCP.setName_and_type_index(value3); + } + } else if (!(constant instanceof ConstantUtf8) + && !(constant instanceof ConstantMethodType) + && constant instanceof ConstantInvokeDynamic) { + ConstantInvokeDynamic constantInvokeDynamic = (ConstantInvokeDynamic) constant; + ConstantPool constantPool2 = constantPoolGen.getConstantPool(); + ConstantNameAndType constantNameAndType2; + ConstantNameAndType constantNameAndType3 = + constantNameAndType2 = + (ConstantNameAndType) + constantPoolGen.getConstant( + constantInvokeDynamic.getBootstrapMethodAttrIndex2()); + String text23 = constantNameAndType3.getText2(constantPool2); + String text6 = constantNameAndType3.getText(constantPool2); + if (text23.contains(")L")) { + String text7 = + text23 + .substring(text23.lastIndexOf(")L") + 2, text23.length() - 1) + .replace('/', '.'); + if (ParameterNameTable.getLookupTable( + NamingContext.getParameterNameTable(this.namingContext)) + .getText(text7) + != null) { + String text8 = null; + if (classGen.getAttributes() != null) { + Attribute[] attributes; + int value4 = (attributes = classGen.getAttributes()).length; + int value5; + for (int value6 = value5 = 0; value6 < value4; value6 = ++value5) { + int[] values; + Attribute attribute; + if ((attribute = attributes[value5]) instanceof BootstrapMethods + && (values = + ((BootstrapMethods) attribute) + .getBootstrapMethods()[ + constantInvokeDynamic.getBootstrapMethodAttrIndex()] + .getBootstrapArguments()) + != null) { + int[] values2 = values; + int value7 = values.length; + int value8; + for (int value9 = value8 = 0; value9 < value7; value9 = ++value8) { + int value10; + if (constantPoolGen.getConstant(value10 = values2[value8]) + instanceof ConstantMethodType) { + ConstantMethodType constantMethodType = + (ConstantMethodType) constantPoolGen.getConstant(value10); + text8 = + ((ConstantUtf8) + constantPoolGen.getConstant( + constantMethodType.getDescriptorIndex())) + .getBytes(); + break; + } + } + } + } + } + String text9; + if (text8 != null + && (text9 = + MethodNameTable.getLookupTable2( + NamingContext.getMethodNameTable(this.namingContext)) + .getText("" + text7 + "&" + text6 + "&" + text8)) + != null) { + constantNameAndType2.setName_index(constantPoolGen.addUtf8(text9)); + } + } + } + String text24 = constantNameAndType2.getText2(constantPool2); + String text10 = this.createText(text24); + if (!text24.equals(text10)) { + constantNameAndType2.setSignature_index(constantPoolGen.addUtf8(text10)); + } + } + } + } + int value11; + for (int value12 = value11 = constantPoolGen.getSize() - 1; value12 >= 0; value12 = --value11) { + Constant constant2; + if ((constant2 = constantPoolGen.getConstant(value11)) instanceof ConstantClass) { + ConstantPool constantPool3 = constantPoolGen.getConstantPool(); + ConstantClass constantClass; + String text11 = + ((String) (constantClass = (ConstantClass) constant2).getConstantValue(constantPool3)) + .replace('/', '.'); + byte value13 = 0; + int value14; + value12 = value14 = 0; + while (value12 < text11.length() && text11.charAt(value14) == '[') { + value12 = ++value14; + } + if (value14 > 0 && text11.endsWith(";") && text11.charAt(value14) == 'L') { + text11 = text11.substring(value14 + 1, text11.length() - 1); + value13 = 1; + } + String text12; + if ((text12 = + ParameterNameTable.getLookupTable( + NamingContext.getParameterNameTable(this.namingContext)) + .getText(text11)) + != null) { + String text13 = text12.replace('.', '/'); + if (value13 != 0) { + text13 = "[L" + text13 + ";"; + for (int value15 = value14; value15 > 1; value15 = value14) { + StringBuilder stringBuilder = new StringBuilder().insert(0, "["); + String text14 = text13; + value14--; + text13 = stringBuilder.append(text14).toString(); + } + } + constantClass.setNameIndex(constantPoolGen.addUtf8(text13)); + Object result; + Map entries; + if ((result = (entries = constantPoolGen.class_table).get(text11.replace('.', '/'))) + != null) { + entries.put(text13, result); + } + } + } else if (!(constant2 instanceof ConstantCP)) { + if (!(constant2 instanceof ConstantUtf8)) { + if (constant2 instanceof ConstantMethodType) { + ConstantMethodType constantMethodType2 = (ConstantMethodType) constant2; + ConstantUtf8 constantUtf8 = + (ConstantUtf8) + constantPoolGen.getConstant(constantMethodType2.getDescriptorIndex()); + constantUtf8.setBytes(this.createText(constantUtf8.getBytes())); + } + } else { + ConstantUtf8 constantUtf82; + String bytes = (constantUtf82 = (ConstantUtf8) constant2).getBytes(); + String text15; + if ((text15 = + ParameterNameTable.getLookupTable( + NamingContext.getParameterNameTable(this.namingContext)) + .getText(bytes)) + != null) { + constantUtf82.setBytes(text15); + } else { + int value16; + value12 = value16 = 0; + while (value12 < bytes.length() && bytes.charAt(value16) == '[') { + value12 = ++value16; + } + if (value16 > 0 && bytes.endsWith(";") && bytes.charAt(value16) == 'L') { + bytes = bytes.substring(value16 + 1, bytes.length() - 1).replace('/', '.'); + String text16; + if ((text16 = + ParameterNameTable.getLookupTable( + NamingContext.getParameterNameTable(this.namingContext)) + .getText(bytes)) + != null) { + String text17 = "[L" + text16.replace('.', '/') + ";"; + for (int value17 = value16; value17 > 1; value17 = value16) { + StringBuilder stringBuilder2 = new StringBuilder().insert(0, "["); + String text18 = text17; + value16--; + text17 = stringBuilder2.append(text18).toString(); + } + constantUtf82.setBytes(text17); + continue; + } + } + if (bytes.startsWith("L") && bytes.endsWith(";")) { + String text19 = bytes.substring(1, bytes.length() - 1).replace('/', '.'); + String text20; + if ((text20 = + ParameterNameTable.getLookupTable( + NamingContext.getParameterNameTable(this.namingContext)) + .getText(text19)) + != null) { + String text21 = "L" + text20.replace('.', '/') + ";"; + constantUtf82.setBytes(text21); + } + } + } + } + } + } + } + + public static boolean isEnabled() { + return enabled; + } + + public void processEnabled( + ClassGen classGen, + String text, + String text2, + String text3, + boolean matches, + boolean matches2) { + if (matches) { + ClassGen classGen2 = classGen; + do { + String superclassName = classGen2.getSuperclassName(); + if ((classGen2 = this.classStorage.getClassGen(superclassName)) != null) { + MethodNameTable.getLookupTable2(NamingContext.getMethodNameTable(this.namingContext)) + .processText("" + classGen2.getClassName() + "&" + text + "&" + text3, text2); + if (classGen2.isEnabled2()) { + MethodNameTable.getLookupTable5(NamingContext.getMethodNameTable(this.namingContext)) + .processText("" + classGen2.getClassName() + "&" + text, text2); + } + MethodNameTable.getLookupTable3(NamingContext.getMethodNameTable(this.namingContext)) + .processText( + "" + classGen2.getClassName() + "&" + text2 + "&" + NameUtils.getText(text3), + "&"); + } + } while (classGen2 != null); + } + int value; + Vector vector; + for (int value2 = + value = (vector = this.classHierarchy.getValues(classGen.getClassName())).size() - 1; + value2 >= 0; + value2 = value) { + ClassGen classGen3 = (ClassGen) vector.get(value); + NameRenamer nameRenamer; + if (matches2 + && Configuration.getRenamingOptions().isText() + && !NameUtils.getText2(classGen.getClassName()) + .equals(NameUtils.getText2(classGen3.getClassName()))) { + nameRenamer = this; + MethodNameTable.getLookupTable3(NamingContext.getMethodNameTable(this.namingContext)) + .processText( + "" + classGen3.getClassName() + "&" + text2 + "&" + NameUtils.getText(text3), "&"); + } else { + MethodNameTable.getLookupTable2(NamingContext.getMethodNameTable(this.namingContext)) + .processText("" + classGen3.getClassName() + "&" + text + "&" + text3, text2); + if (classGen3.isEnabled2()) { + MethodNameTable.getLookupTable5(NamingContext.getMethodNameTable(this.namingContext)) + .processText("" + classGen3.getClassName() + "&" + text, text2); + } + nameRenamer = this; + MethodNameTable.getLookupTable3(NamingContext.getMethodNameTable(this.namingContext)) + .processText( + "" + classGen3.getClassName() + "&" + text2 + "&" + NameUtils.getText(text3), "&"); + } + NameRenamer nameRenamer2 = nameRenamer; + value--; + nameRenamer2.processEnabled(classGen3, text, text2, text3, matches, matches2); + } + } + + public void processConstantPoolGen(List values, ConstantPoolGen constantPoolGen) { + if (values != null) { + int value; + for (int value2 = value = values.size() - 1; value2 >= 0; value2 = value) { + Object result = values.get(value); + value--; + this.processConstantPoolGen((AnnotationEntryGen) result, constantPoolGen); + } + } + } + + public void processClassGen2(ClassGen classGen) { + String className = classGen.getClassName(); + Field[] fields = classGen.getFields(); + if (!Configuration.getRenamingOptions().isFieldsNamingEnabled()) { + FieldNameTable.getNameGenerator(NamingContext.getFieldNameTable(this.namingContext)).reset(); + } + int value; + for (int value2 = value = fields.length - 1; value2 >= 0; value2 = --value) { + Field field; + Field field2 = field = fields[value]; + String text = field2.getText(); + String text2 = field2.getText2(); + String text3; + if ((text3 = + FieldNameTable.getLookupTable(NamingContext.getFieldNameTable(this.namingContext)) + .getText("" + className + "&" + text + "&" + text2)) + == null) { + NameRenamer nameRenamer = this; + for (text3 = + FieldNameTable.getNameGenerator(NamingContext.getFieldNameTable(this.namingContext)) + .nextName(); + nameRenamer.matchesEnabled(classGen, text3, text2, !field.isEnabled9()); + text3 = + FieldNameTable.getNameGenerator(NamingContext.getFieldNameTable(this.namingContext)) + .nextName()) { + nameRenamer = this; + } + FieldNameTable.getLookupTable(NamingContext.getFieldNameTable(this.namingContext)) + .processText("" + className + "&" + text + "&" + text2, text3); + FieldNameTable.getLookupTable3(NamingContext.getFieldNameTable(this.namingContext)) + .processText("" + className + "&" + text3 + "&" + text2, "&"); + } + if (!field.isEnabled9()) { + this.processText(classGen, text, text3, text2); + } + } + } + + public void processConstantPoolGen( + ElementValueGen elementValueGen, ConstantPoolGen constantPoolGen) { + if (elementValueGen instanceof AnnotationElementValueGen) { + this.processConstantPoolGen( + ((AnnotationElementValueGen) elementValueGen).getAnnotation(), constantPoolGen); + } else { + int value; + if (elementValueGen instanceof ArrayElementValueGen) { + List values; + for (int value2 = + value = + (values = ((ArrayElementValueGen) elementValueGen).getElementValues()).size() + - 1; + value2 >= 0; + value2 = value) { + Object result = values.get(value); + value--; + this.processConstantPoolGen((ElementValueGen) result, constantPoolGen); + } + } else { + if (elementValueGen instanceof ClassElementValueGen) { + return; + } + if (elementValueGen instanceof EnumElementValueGen) { + EnumElementValueGen enumElementValueGen; + String typeIdx2 = + (enumElementValueGen = (EnumElementValueGen) elementValueGen).getTypeIdx2(); + String text = null; + if (typeIdx2.startsWith("L") && typeIdx2.endsWith(";")) { + String text2; + text = text2 = typeIdx2.substring(1, typeIdx2.length() - 1).replace('/', '.'); + String text3; + if ((text3 = + ParameterNameTable.getLookupTable( + NamingContext.getParameterNameTable(this.namingContext)) + .getText(text2)) + != null) { + String text4 = "L" + text3.replace('.', '/') + ";"; + enumElementValueGen.setTypeIdx(constantPoolGen.addUtf8(text4)); + } + } + if (text != null) { + String valueIdx2 = enumElementValueGen.getValueIdx2(); + String text5 = "" + text + "&" + valueIdx2 + "&" + typeIdx2; + if (FieldNameTable.getLookupTable(NamingContext.getFieldNameTable(this.namingContext)) + .matchesText(text5)) { + String text6 = + FieldNameTable.getLookupTable(NamingContext.getFieldNameTable(this.namingContext)) + .getText(text5); + enumElementValueGen.setValueIdx(constantPoolGen.addUtf8(text6)); + return; + } + } + } else if (elementValueGen instanceof SimpleElementValueGen) { + } + } + } + } + + public void processClassGen3(ClassGen classGen) { + String className = classGen.getClassName(); + Method[] methods; + int value; + for (int value2 = value = (methods = classGen.getMethods()).length - 1; + value2 >= 0; + value2 = --value) { + Method method; + Method method2 = method = methods[value]; + String text = method2.getText(); + String text2 = method2.getText2(); + String text3; + if (!method2.isEnabled9()) { + text3 = this.createText(classGen, text, text2); + } else { + text3 = + MethodNameTable.getLookupTable2(NamingContext.getMethodNameTable(this.namingContext)) + .getText("" + className + "&" + text + "&" + text2); + } + boolean matches = + Configuration.getRenamingOptions().matchesClassGen(this.classStorage, classGen); + if (text3 == null && matches) { + text3 = + MethodNameTable.getLookupTable4(NamingContext.getMethodNameTable(this.namingContext)) + .getText("" + text + "&" + NameUtils.getText(text2)); + } + if (text3 == null) { + if (!Configuration.getRenamingOptions().isEnabled8() && !classGen.isEnabled2()) { + MethodNameTable.getNameGenerator(NamingContext.getMethodNameTable(this.namingContext)) + .reset(); + } + String text4; + byte value3; + ClassGen classGen2; + do { + text3 = + MethodNameTable.getNameGenerator(NamingContext.getMethodNameTable(this.namingContext)) + .nextName(); + text4 = NameUtils.getText(text2); + if (!method.isEnabled9()) { + value3 = 1; + classGen2 = classGen; + } else { + value3 = 0; + classGen2 = classGen; + } + } while (this.matchesEnabled(classGen, text3, text4, value3 != 0, classGen2.isEnabled5())); + } + MethodNameTable.getLookupTable2(NamingContext.getMethodNameTable(this.namingContext)) + .processText("" + className + "&" + text + "&" + text2, text3); + if (classGen.isEnabled2()) { + MethodNameTable.getLookupTable5(NamingContext.getMethodNameTable(this.namingContext)) + .processText("" + className + "&" + text, text3); + } + MethodNameTable.getLookupTable3(NamingContext.getMethodNameTable(this.namingContext)) + .processText("" + className + "&" + text3 + "&" + NameUtils.getText(text2), "&"); + if (!method.isEnabled9()) { + this.processEnabled( + classGen, + text, + text3, + text2, + classGen.isEnabled5(), + NameUtils.matchesAccessFlags2(method)); + } + if (Configuration.getRenamingOptions().isEnabled8() && !text3.equals(text)) { + MethodNameTable.getLookupTable4(NamingContext.getMethodNameTable(this.namingContext)) + .processText("" + text + "&" + NameUtils.getText(text2), text3); + } + } + } + + public String createText(String text) { + String text2; + String text3 = text; + int value; + if (text3.contains(">.")) { + for (int value2 = value = 0; value2 < text3.length(); value2 = ++value) { + if (text3.charAt(value) == 'L') { + int value3; + int value4 = value3 = value + 1; + int value5 = 0; + int value6; + value2 = value6 = value3; + while (true) { + if (value2 >= text3.length()) { + text2 = text3; + break; + } + if (text3.charAt(value6) == '<') { + value5++; + } + if (text3.charAt(value6) == '>') { + value5--; + } + if (text3.charAt(value6) == ';' && value5 == 0) { + value4 = value6; + text2 = text3; + break; + } + value2 = ++value6; + } + String text4; + if ((text4 = text2.substring(value3, value4)).indexOf(46) > 0) { + String text5; + String text6 = text5 = text4; + while (text6.contains(">")) { + int value7 = text5.indexOf(62); + int value8 = text5.lastIndexOf(60, value7); + text6 = text5 = "" + text5.substring(0, value8) + text5.substring(value7 + 1); + } + String text7 = text5.replace('.', '$').replace('/', '.'); + String text8; + if ((text8 = + ParameterNameTable.getLookupTable( + NamingContext.getParameterNameTable(this.namingContext)) + .getText(text7)) + != null + && !text8.equals(text7)) { + text3 = + "" + + text3.substring(0, value3) + + text8.replace('.', '/') + + text3.substring(value3 + text4.length()); + } + } + } + } + } + int value9; + for (int value10 = value9 = text3.length() - 1; value10 >= 0; value10 = --value9) { + if (text3.charAt(value9) == 'L') { + int value11 = text3.indexOf(59, value9); + int value12 = text3.indexOf(60, value9); + if (value11 == -1) { + value11 = value12; + } + if (value12 != -1 && value12 < value11) { + value11 = value12; + } + if (value11 > value9) { + String text9 = text3.substring(value9 + 1, value11).replace('/', '.'); + String text10; + if ((text10 = + ParameterNameTable.getLookupTable( + NamingContext.getParameterNameTable(this.namingContext)) + .getText(text9)) + != null + && !text10.equals(text9)) { + text3 = + "" + + text3.substring(0, value9 + 1) + + text10.replace('.', '/') + + text3.substring(value9 + text9.length() + 1); + } + } + } + } + return text3; + } + + public void processClassGen4(ClassGen classGen) { + int value; + Field[] fields; + for (int value2 = value = (fields = classGen.getFields()).length - 1; + value2 >= 0; + value2 = --value) { + Field field = fields[value]; + String text = + FieldNameTable.getLookupTable(NamingContext.getFieldNameTable(this.namingContext)) + .getText( + "" + classGen.getClassName() + "&" + field.getText() + "&" + field.getText2()); + Type type = + NameUtils.getType( + field.getType(), + ParameterNameTable.getLookupTable( + NamingContext.getParameterNameTable(this.namingContext))); + boolean matches; + if (!(matches = + Configuration.getMemberOrderOptions() + .matchesField(this.classStorage, classGen, field)) + && !field.isEnabled9() + && (ParameterNameTable.getLookupTable2( + NamingContext.getParameterNameTable(this.namingContext)) + .matchesText(classGen.getClassName()) + || Configuration.getRenamingOptions().isForceDefaultPackageEnabled())) { + matches = true; + } + if (!text.equals(field.getText()) + || type != null + || matches + || field.getAnnotationEntries().length > 0) { + FieldGen fieldGen = new FieldGen(field, classGen.getConstantPool()); + if (!text.equals(field.getText())) { + fieldGen.setName(text); + RenameStatistics.count2++; + } + if (type != null) { + fieldGen.setType(type); + FieldNameTable.getLookupTable2(NamingContext.getFieldNameTable(this.namingContext)) + .processText(field.getText2(), fieldGen.getText()); + } + if (matches) { + NameUtils.processAccessFlags(fieldGen); + } + this.processConstantPoolGen(fieldGen.getAnnotationEntryGens(), classGen.getConstantPool()); + classGen.replaceField(field, fieldGen.getField()); + } + } + } + + public void update3() { + ClassNameTable.getLookupTable2(NamingContext.getClassNameTable(this.namingContext)) + .processText("", ""); + Iterator iterator2; + Iterator iterator3 = iterator2 = this.classHierarchy.getValues().iterator(); + while (iterator3.hasNext()) { + ClassGen classGen = (ClassGen) iterator2.next(); + if (Configuration.getIgnoreClassesOptions().matchesClassGen(this.classStorage, classGen)) { + iterator3 = iterator2; + } else { + this.processClassGen6(classGen); + this.processClassGen3(classGen); + this.processClassGen2(classGen); + iterator3 = iterator2; + } + } + if (Configuration.getRenamingOptions().isClassesNamingEnabled()) { + this.update4(); + } + } + + public void processClassGen5(ClassGen classGen) { + Method[] methods; + int value; + for (int value2 = value = (methods = classGen.getMethods()).length - 1; + value2 >= 0; + value2 = value) { + Method method; + MethodGen methodGen = + MethodFactory.createMethodGen( + method = methods[value], + classGen.getClassName(), + classGen.getConstantPool(), + classGen.getConstantPool().getConstantPool()); + this.processMethodGen(classGen, methodGen); + this.nameMappingEntry.processMethodGen(classGen.getClassName(), methodGen); + String text = + MethodNameTable.getLookupTable2(NamingContext.getMethodNameTable(this.namingContext)) + .getText( + "" + classGen.getClassName() + "&" + method.getText() + "&" + method.getText2()); + if (!methodGen.getName().equals(text)) { + methodGen.setName(text); + RenameStatistics.count++; + } + byte value3 = 0; + Type[] types; + int value4; + for (int value5 = value4 = (types = methodGen.getArgumentTypes()).length - 1; + value5 >= 0; + value5 = --value4) { + Type type; + if ((type = + NameUtils.getType( + types[value4], + ParameterNameTable.getLookupTable( + NamingContext.getParameterNameTable(this.namingContext)))) + != null) { + methodGen.setArgumentType(value4, type); + value3 = 1; + } + } + Type type2; + if ((type2 = + NameUtils.getType( + methodGen.getReturnType(), + ParameterNameTable.getLookupTable( + NamingContext.getParameterNameTable(this.namingContext)))) + != null) { + methodGen.setReturnType(type2); + value3 = 1; + } + if (value3 != 0) { + MethodNameTable.getLookupTable(NamingContext.getMethodNameTable(this.namingContext)) + .processText(method.getText2(), methodGen.getText()); + } + if (Configuration.getMemberOrderOptions().matchesMethod(this.classStorage, classGen, method) + || !method.isEnabled9() + && (ParameterNameTable.getLookupTable2( + NamingContext.getParameterNameTable(this.namingContext)) + .matchesText(classGen.getClassName()) + || Configuration.getRenamingOptions().isForceDefaultPackageEnabled())) { + NameUtils.processAccessFlags(methodGen); + } + this.processConstantPoolGen(methodGen.getAnnotationEntryGens(), classGen.getConstantPool()); + int value6; + for (int value7 = value6 = methodGen.getArgumentTypes().length - 1; + value7 >= 0; + value7 = value6) { + List annotationsOnParameter = methodGen.getAnnotationsOnParameter(value6); + value6--; + this.processConstantPoolGen(annotationsOnParameter, classGen.getConstantPool()); + } + Method method2 = method; + value--; + classGen.replaceMethod(method2, methodGen.getMethod()); + } + } + + public void processText(ClassGen classGen, String text, String text2, String text3) { + Vector vector; + int value; + for (int value2 = + value = (vector = this.classHierarchy.getValues(classGen.getClassName())).size() - 1; + value2 >= 0; + value2 = value) { + ClassGen classGen2; + ClassGen classGen3 = classGen2 = (ClassGen) vector.get(value); + FieldNameTable.getLookupTable(NamingContext.getFieldNameTable(this.namingContext)) + .processText("" + classGen2.getClassName() + "&" + text + "&" + text3, text2); + FieldNameTable.getLookupTable3(NamingContext.getFieldNameTable(this.namingContext)) + .processText("" + classGen2.getClassName() + "&" + text2 + "&" + text3, "&"); + value--; + this.processText(classGen3, text, text2, text3); + } + } + + public static NamingContext getNamingContext(NameRenamer nameRenamer) { + return nameRenamer.namingContext; + } + + public void processClassGen6(ClassGen classGen) { + String className = classGen.getClassName(); + if (!ParameterNameTable.getLookupTable(NamingContext.getParameterNameTable(this.namingContext)) + .matchesText(className)) { + String text2 = NameUtils.getText2(className); + String text = this.createText2(text2); + if (Configuration.getRenamingOptions().isText() + && (!text2.equals(text) + || Configuration.getRenamingOptions().isForceDefaultPackageEnabled())) { + text = Configuration.getRenamingOptions().getDefaultPackage(); + ParameterNameTable.getLookupTable2(NamingContext.getParameterNameTable(this.namingContext)) + .processText(className, "&"); + } + if (text.length() > 0) { + text = "" + text + "."; + } + if (!Configuration.getRenamingOptions().getNameGenerationOptions().isClassesNamingEnabled()) { + ParameterNameTable.getNameGenerator(NamingContext.getParameterNameTable(this.namingContext)) + .reset(); + } + String text3; + do { + text3 = + "" + + text + + ParameterNameTable.getNameGenerator( + NamingContext.getParameterNameTable(this.namingContext)) + .nextName(); + } while (ParameterNameTable.getLookupTable3( + NamingContext.getParameterNameTable(this.namingContext)) + .matchesText(text3) + || this.classStorage.getClassGen(text3) != null); + ParameterNameTable.getLookupTable(NamingContext.getParameterNameTable(this.namingContext)) + .processText(className, text3); + ParameterNameTable.getLookupTable3(NamingContext.getParameterNameTable(this.namingContext)) + .processText(text3, className); + } + } + + public void processClassGen7(ClassGen classGen) { + String className = classGen.getClassName(); + Field[] fields; + int value; + for (int value2 = value = (fields = classGen.getFields()).length - 1; + value2 >= 0; + value2 = --value) { + Field field = fields[value]; + if (!Configuration.getRenamingOptions() + .getKeepNamesOptions() + .matchesField(this.classStorage, classGen, field)) { + String text = field.getText(); + String text2 = field.getText2(); + if (Configuration.getRenamingOptions().getNameGenerationOptions().isFieldsNamingEnabled()) { + MainNameGenerator.processText2(text); + } + if (!FieldNameTable.getLookupTable(NamingContext.getFieldNameTable(this.namingContext)) + .matchesText("" + className + "&" + text + "&" + text2)) { + FieldNameTable.getLookupTable(NamingContext.getFieldNameTable(this.namingContext)) + .processText("" + className + "&" + text + "&" + text2, text); + FieldNameTable.getLookupTable3(NamingContext.getFieldNameTable(this.namingContext)) + .processText("" + className + "&" + text + "&" + text2, "&"); + if (!field.isEnabled9()) { + this.processText(classGen, text, text, text2); + } + } else if (!field.isEnabled9()) { + this.processText( + classGen, + text, + FieldNameTable.getLookupTable(NamingContext.getFieldNameTable(this.namingContext)) + .getText("" + className + "&" + text + "&" + text2), + text2); + } + } + } + ClassGen classGen2 = classGen; + do { + String superclassName = classGen2.getSuperclassName(); + int value3; + if ((classGen2 = this.classStorage.getClassGen(superclassName)) != null) { + Field[] fields2; + for (int value4 = value3 = (fields2 = classGen2.getFields()).length - 1; + value4 >= 0; + value4 = --value3) { + Field field2 = fields2[value3]; + if (!Configuration.getRenamingOptions() + .getKeepNamesOptions() + .matchesField(this.classStorage, classGen, field2)) { + String text3 = field2.getText(); + String text22 = field2.getText2(); + if (Configuration.getRenamingOptions() + .getNameGenerationOptions() + .isFieldsNamingEnabled()) { + MainNameGenerator.processText2(text3); + } + if (!FieldNameTable.getLookupTable(NamingContext.getFieldNameTable(this.namingContext)) + .matchesText("" + superclassName + "&" + text3 + "&" + text22)) { + FieldNameTable.getLookupTable(NamingContext.getFieldNameTable(this.namingContext)) + .processText("" + superclassName + "&" + text3 + "&" + text22, text3); + FieldNameTable.getLookupTable3(NamingContext.getFieldNameTable(this.namingContext)) + .processText("" + superclassName + "&" + text3 + "&" + text22, "&"); + if (!field2.isEnabled9()) { + this.processText(classGen2, text3, text3, text22); + } + } else if (!field2.isEnabled9()) { + this.processText( + classGen2, + text3, + FieldNameTable.getLookupTable(NamingContext.getFieldNameTable(this.namingContext)) + .getText("" + superclassName + "&" + text3 + "&" + text22), + text22); + } + } + } + } + } while (classGen2 != null); + } + + public String createText(ClassGen classGen, String text, String text2) { + String text3; + if ((text3 = + MethodNameTable.getLookupTable2(NamingContext.getMethodNameTable(this.namingContext)) + .getText("" + classGen.getClassName() + "&" + text + "&" + text2)) + != null) { + return text3; + } + Vector vector; + int value; + for (int value2 = + value = (vector = this.classHierarchy.getValues(classGen.getClassName())).size() - 1; + value2 >= 0; + value2 = --value) { + String text4; + if ((text4 = this.createText((ClassGen) vector.get(value), text, text2)) != null) { + return text4; + } + } + return null; + } + + public void update4() { + for (String text : + ((Iterable) + ((Iterable) + ParameterNameTable.getLookupTable( + NamingContext.getParameterNameTable(this.namingContext)) + .getEntries2()))) { + String text2 = + ParameterNameTable.getLookupTable(NamingContext.getParameterNameTable(this.namingContext)) + .getText(text); + String text3 = this.createText3(text); + if (!text2.equals(text3)) { + ParameterNameTable.getLookupTable(NamingContext.getParameterNameTable(this.namingContext)) + .processText(text, text3); + ParameterNameTable.getLookupTable3(NamingContext.getParameterNameTable(this.namingContext)) + .processText(text2); + ParameterNameTable.getLookupTable3(NamingContext.getParameterNameTable(this.namingContext)) + .processText(text3, text); + } + } + } + + public void rename() throws ObfuscationAbortException { + this.classHierarchy.update3(); + this.update(); + this.update3(); + this.update2(); + this.update6(); + this.update7(); + Configuration.getMappingOptions().renamingLog = + new RenamingLog( + ParameterNameTable.getLookupTable( + NamingContext.getParameterNameTable(this.namingContext)), + MethodNameTable.getLookupTable2(NamingContext.getMethodNameTable(this.namingContext)), + FieldNameTable.getLookupTable(NamingContext.getFieldNameTable(this.namingContext)), + this.nameMappingEntry.getValues2(), + this.nameMappingEntry.getValues(), + this.nameMappingEntry.getLookupTable2(), + MethodNameTable.getLookupTable5(NamingContext.getMethodNameTable(this.namingContext))); + Configuration.getMappingOptions().lookupTable = + ParameterNameTable.getLookupTable3(NamingContext.getParameterNameTable(this.namingContext)); + Configuration.getMappingOptions().lookupTable2 = + ClassNameTable.getLookupTable2(NamingContext.getClassNameTable(this.namingContext)); + } + + public void processConstantPoolGen( + AnnotationEntryGen[] annotationEntryGens, ConstantPoolGen constantPoolGen) { + if (annotationEntryGens != null) { + int value; + for (int value2 = value = annotationEntryGens.length - 1; value2 >= 0; value2 = value) { + int value3 = value; + value--; + this.processConstantPoolGen(annotationEntryGens[value3], constantPoolGen); + } + } + } + + public void processMethodGen(ClassGen classGen, MethodGen methodGen) { + int value; + int value2 = + value = + Configuration.getRenamingOptions() + .getLocalVariableOptions() + .calculateCount(this.classStorage, classGen, methodGen); + Configuration.getRenamingOptions().getLocalVariableOptions(); + if (value2 == 4) { + methodGen.getVariable_vec(); + } else { + Configuration.getRenamingOptions().getLocalVariableOptions(); + int value3 = value == 3 ? 1 : 0; + LocalVariableGen[] localVariables = methodGen.getLocalVariables(); + int value4 = methodGen.getArgumentNames().length; + if (!methodGen.isEnabled11()) { + value4++; + } + Type[] types; + int value5 = (types = methodGen.getArgumentTypes()).length; + int value6; + for (int value7 = value6 = 0; value7 < value5; value7 = ++value6) { + Type type; + if ((type = types[value6]) == Type.LONG || type == Type.DOUBLE) { + value4++; + } + } + PackageNameTable.getNameGenerator(NamingContext.getPackageNameTable(this.namingContext)) + .reset(); + LowercaseNameGenerator lowercaseNameGenerator = null; + if (Configuration.getObfuscationOptions().isEnabled3()) { + lowercaseNameGenerator = new LowercaseNameGenerator(); + } + int value8; + for (int value9 = value8 = localVariables.length - 1; value9 >= 0; value9 = --value8) { + LocalVariableGen localVariableGen; + Type type2; + if ((type2 = + NameUtils.getType( + (localVariableGen = localVariables[value8]).getType(), + ParameterNameTable.getLookupTable( + NamingContext.getParameterNameTable(this.namingContext)))) + != null) { + localVariableGen.setType(type2); + } + try { + if (methodGen.getAnnotationsOnParameter(localVariableGen.getIndex()) != null) { + continue; + } + } catch (ArrayIndexOutOfBoundsException arrayIndexOutOfBoundsException) { + } + Configuration.getRenamingOptions().getLocalVariableOptions(); + if (value == 5) { + if (localVariableGen.getIndex() >= value4) { + localVariableGen.setName( + Configuration.getObfuscationOptions().isEnabled3() + ? lowercaseNameGenerator.nextName() + : Configuration.getRenamingOptions().getNameGenerationOptions().getText()); + } + } else { + Configuration.getRenamingOptions().getLocalVariableOptions(); + if (value == 6) { + if (localVariableGen.getIndex() < value4) { + localVariableGen.setName( + Configuration.getObfuscationOptions().isEnabled3() + ? lowercaseNameGenerator.nextName() + : Configuration.getRenamingOptions().getNameGenerationOptions().getText()); + } else { + localVariableGen.setName( + Configuration.getObfuscationOptions().isEnabled3() + ? lowercaseNameGenerator.nextName() + : Configuration.getRenamingOptions().getNameGenerationOptions().getText()); + } + } else { + Configuration.getRenamingOptions().getLocalVariableOptions(); + if (value == 1) { + localVariableGen.setName( + Configuration.getRenamingOptions().getNameGenerationOptions().getText()); + } else if (value3 == 0) { + localVariableGen.setName( + PackageNameTable.getNameGenerator( + NamingContext.getPackageNameTable(this.namingContext)) + .nextName()); + } + } + } + } + } + } + + public void update6() { + Iterator iterator2 = this.classHierarchy.getValues().iterator(); + label35: + while (true) { + for (Iterator iterator3 = iterator2; iterator3.hasNext(); iterator3 = iterator2) { + ClassGen classGen = (ClassGen) iterator2.next(); + if (!Configuration.getIgnoreClassesOptions().matchesClassGen(this.classStorage, classGen)) { + this.processClassGen(classGen); + ConstantPoolGen constantPool = classGen.getConstantPool(); + this.processConstantPoolGen(classGen.getAttributes(), constantPool); + int value; + Method[] methods; + for (int value2 = value = (methods = classGen.getMethods()).length - 1; + value2 >= 0; + value2 = value) { + Method method = methods[value]; + value--; + this.processConstantPoolGen(method.getAttributes(), constantPool); + } + Field[] fields; + int value3; + for (int value4 = value3 = (fields = classGen.getFields()).length - 1; + value4 >= 0; + value4 = value3) { + Field field = fields[value3]; + value3--; + this.processConstantPoolGen(field.getAttributes(), constantPool); + } + continue label35; + } + } + return; + } + } + + public static ClassStorage getClassStorage(NameRenamer nameRenamer) { + return nameRenamer.classStorage; + } + + public boolean matchesClassGen(ClassGen classGen) { + int value; + Method[] methods; + for (int value2 = value = (methods = classGen.getMethods()).length - 1; + value2 >= 0; + value2 = --value) { + if (methods[value].isEnabled14()) { + return true; + } + } + return false; + } + + public void processConstantPoolGen( + AnnotationEntryGen annotationEntryGen, ConstantPoolGen constantPoolGen) { + String text; + AnnotationEntryGen annotationEntryGen2; + label29: + { + String text2 = annotationEntryGen.getText2(); + text = null; + if (text2.startsWith("L") && text2.endsWith(";")) { + String text3; + text = text3 = text2.substring(1, text2.length() - 1).replace('/', '.'); + String text4; + if ((text4 = + ParameterNameTable.getLookupTable( + NamingContext.getParameterNameTable(this.namingContext)) + .getText(text3)) + != null) { + String text5 = "L" + text4.replace('.', '/') + ";"; + annotationEntryGen2 = annotationEntryGen; + annotationEntryGen.setTypeIndex(constantPoolGen.addUtf8(text5)); + break label29; + } + text = + ParameterNameTable.getLookupTable3( + NamingContext.getParameterNameTable(this.namingContext)) + .getText(text); + } + annotationEntryGen2 = annotationEntryGen; + } + List values; + int value; + for (int value2 = value = (values = annotationEntryGen2.getValues()).size() - 1; + value2 >= 0; + value2 = value) { + ElementValuePairGen elementValuePairGen = (ElementValuePairGen) values.get(value); + if (text != null) { + String text6 = elementValuePairGen.getText(); + String text7 = "" + text + "&" + text6; + if (MethodNameTable.getLookupTable5(NamingContext.getMethodNameTable(this.namingContext)) + .matchesText(text7)) { + String text8 = + MethodNameTable.getLookupTable5(NamingContext.getMethodNameTable(this.namingContext)) + .getText(text7); + elementValuePairGen.setNameIdx(constantPoolGen.addUtf8(text8)); + } + } + value--; + this.processConstantPoolGen(elementValuePairGen.getValue(), constantPoolGen); + } + } + + public void processConstantPoolGen(Attribute[] attributes, ConstantPoolGen constantPoolGen) { + int value; + for (int value2 = value = attributes.length - 1; value2 >= 0; value2 = --value) { + Attribute attribute; + if ((attribute = attributes[value]) instanceof Code) { + Code code = (Code) attribute; + this.processConstantPoolGen(code.getAttributes(), constantPoolGen); + } else if (!(attribute instanceof ConstantValue) + && !(attribute instanceof Deprecated) + && !(attribute instanceof ExceptionTable)) { + if (attribute instanceof InnerClasses) { + InnerClass[] innerClasss; + if ((innerClasss = ((InnerClasses) attribute).getInnerClasses()).length > 0) { + ConstantPool constantPool = constantPoolGen.getConstantPool(); + int value3; + for (int value4 = value3 = innerClasss.length - 1; value4 >= 0; value4 = --value3) { + InnerClass innerClass = innerClasss[value3]; + if (!constantPool + .createText(innerClass.getInner_class_index(), (byte) 7) + .contains("$")) { + innerClass.setInner_name_index(0); + } + } + } + } else if (!(attribute instanceof LineNumberTable) + && !(attribute instanceof LocalVariableTable) + && !(attribute instanceof PMGClass)) { + if (attribute instanceof Signature) { + Signature signature = (Signature) attribute; + String text = ((Signature) attribute).getText(); + String text2 = this.createText(text); + signature.setSignatureIndex(constantPoolGen.addUtf8(text2)); + } else if (!(attribute instanceof SourceFile) + && !(attribute instanceof StackMap) + && !(attribute instanceof Synthetic)) { + if (attribute instanceof EnclosingMethod) { + EnclosingMethod enclosingMethod; + if ((enclosingMethod = (EnclosingMethod) attribute).getMethodIndex() != 0) { + ConstantPool constantPool2 = constantPoolGen.getConstantPool(); + String text3 = + enclosingMethod.getEnclosingClass().getBytes(constantPool2).replace('/', '.'); + String text4; + if ((text4 = + ParameterNameTable.getLookupTable3( + NamingContext.getParameterNameTable(this.namingContext)) + .getText(text3)) + != null) { + text3 = text4; + } + ConstantNameAndType constantNameAndType; + if ((constantNameAndType = enclosingMethod.getEnclosingMethod()) != null) { + String text5 = constantNameAndType.getText(constantPool2); + String text22 = constantNameAndType.getText2(constantPool2); + String text6 = + MethodNameTable.getLookupTable2( + NamingContext.getMethodNameTable(this.namingContext)) + .getText("" + text3 + "&" + text5 + "&" + text22); + String text7 = + MethodNameTable.getLookupTable( + NamingContext.getMethodNameTable(this.namingContext)) + .getText(text22); + if (text6 != null && !text6.equals(text5) || text7 != null) { + if (text6 == null) { + text6 = text5; + } + if (text7 == null) { + text7 = text22; + } + int value5 = constantPoolGen.addNameAndType(text6, text7); + enclosingMethod.setMethodIndex(value5); + } + } + } + } else if (!(attribute instanceof NestHost) + && !(attribute instanceof NestMembers) + && attribute instanceof Unknown) { + } + } + } + } + } + } + + public static LookupTable getLookupTable() { + return lookupTable; + } + + public boolean matchesMethod(String text, Method method) { + return method.isEnabled14() + || this.classHierarchy.matchesText(text, method.getText(), method.getText2()) + ? true + : "".equals(method.getText()) + || "".equals(method.getText()) + || "main".equals(method.getText()) + && "([Ljava/lang/String;)V".equals(method.getText2()); + } + + public void processClassGen8(ClassGen classGen) { + String className = classGen.getClassName(); + int value; + Method[] methods; + for (int value2 = value = (methods = classGen.getMethods()).length - 1; + value2 >= 0; + value2 = --value) { + Method method = methods[value]; + if (this.matchesMethod(className, method) + || !Configuration.getRenamingOptions() + .getKeepNamesOptions() + .matchesMethod(this.classStorage, classGen, method)) { + String text = method.getText(); + String text2 = method.getText2(); + if (Configuration.getRenamingOptions() + .getNameGenerationOptions() + .isMethodsNamingEnabled()) { + MainNameGenerator.processText(text); + } + if (!MethodNameTable.getLookupTable2(NamingContext.getMethodNameTable(this.namingContext)) + .matchesText("" + className + "&" + text + "&" + text2)) { + MethodNameTable.getLookupTable2(NamingContext.getMethodNameTable(this.namingContext)) + .processText("" + className + "&" + text + "&" + text2, text); + MethodNameTable.getLookupTable3(NamingContext.getMethodNameTable(this.namingContext)) + .processText("" + className + "&" + text + "&" + NameUtils.getText(text2), "&"); + if (!method.isEnabled9()) { + this.processEnabled( + classGen, + text, + text, + text2, + classGen.isEnabled5(), + NameUtils.matchesAccessFlags2(method)); + } + } else if (!method.isEnabled9()) { + this.processEnabled( + classGen, + text, + MethodNameTable.getLookupTable2(NamingContext.getMethodNameTable(this.namingContext)) + .getText("" + className + "&" + text + "&" + text2), + text2, + classGen.isEnabled5(), + NameUtils.matchesAccessFlags2(method)); + } + } + } + ClassGen classGen2 = classGen; + do { + String superclassName = classGen2.getSuperclassName(); + int value3; + if ((classGen2 = this.classStorage.getClassGen(superclassName)) != null) { + Method[] methods2; + for (int value4 = value3 = (methods2 = classGen2.getMethods()).length - 1; + value4 >= 0; + value4 = --value3) { + Method method2 = methods2[value3]; + if (!this.matchesMethod(superclassName, method2) + && !Configuration.getRenamingOptions() + .getKeepNamesOptions() + .matchesMethod(this.classStorage, classGen, method2)) { + String text3 = method2.getText(); + String text22 = method2.getText2(); + if (Configuration.getRenamingOptions() + .getNameGenerationOptions() + .isMethodsNamingEnabled()) { + MainNameGenerator.processText(text3); + } + if (!MethodNameTable.getLookupTable2( + NamingContext.getMethodNameTable(this.namingContext)) + .matchesText("" + superclassName + "&" + text3 + "&" + text22)) { + MethodNameTable.getLookupTable2(NamingContext.getMethodNameTable(this.namingContext)) + .processText("" + superclassName + "&" + text3 + "&" + text22, text3); + MethodNameTable.getLookupTable3(NamingContext.getMethodNameTable(this.namingContext)) + .processText( + "" + superclassName + "&" + text3 + "&" + NameUtils.getText(text22), "&"); + if (!method2.isEnabled9()) { + this.processEnabled( + classGen2, + text3, + text3, + text22, + classGen2.isEnabled5(), + NameUtils.matchesAccessFlags2(method2)); + } + } else if (!method2.isEnabled9()) { + this.processEnabled( + classGen2, + text3, + MethodNameTable.getLookupTable2( + NamingContext.getMethodNameTable(this.namingContext)) + .getText("" + superclassName + "&" + text3 + "&" + text22), + text22, + classGen2.isEnabled5(), + NameUtils.matchesAccessFlags2(method2)); + } + } + } + } + } while (classGen2 != null); + } + + public String createText2(String text) { + String text2; + if ((text2 = + ClassNameTable.getLookupTable2(NamingContext.getClassNameTable(this.namingContext)) + .getText(text)) + != null) { + return text2; + } + if (Configuration.getRenamingOptions().isEnabled()) { + String text3 = text; + LookupTable lookupTable2 = + ClassNameTable.getLookupTable2(NamingContext.getClassNameTable(this.namingContext)); + String text4 = text3; + lookupTable2.processText(text3, text3); + ClassNameTable.getLookupTable(NamingContext.getClassNameTable(this.namingContext)) + .processText(text3, "&"); + while (text4.lastIndexOf(46) > 0) { + text3 = text3.substring(0, text3.lastIndexOf(46)); + lookupTable2 = + ClassNameTable.getLookupTable2(NamingContext.getClassNameTable(this.namingContext)); + text4 = text3; + lookupTable2.processText(text3, text3); + ClassNameTable.getLookupTable(NamingContext.getClassNameTable(this.namingContext)) + .processText(text3, "&"); + } + return ClassNameTable.getLookupTable2(NamingContext.getClassNameTable(this.namingContext)) + .getText(text); + } else { + StringTokenizer stringTokenizer = new StringTokenizer(text, "."); + String text5 = ""; + label38: + while (true) { + StringTokenizer stringTokenizer2 = stringTokenizer; + while (stringTokenizer2.hasMoreTokens()) { + if (text5.length() > 0) { + text5 = "" + text5 + "."; + } + text5 = "" + text5 + stringTokenizer.nextToken(); + if (ClassNameTable.getLookupTable2(NamingContext.getClassNameTable(this.namingContext)) + .matchesText(text5)) { + continue label38; + } + ClassNameTable.getNameGenerator(NamingContext.getClassNameTable(this.namingContext)) + .reset(); + String text22 = NameUtils.getText2(text5); + String text6; + if ((text6 = + ClassNameTable.getLookupTable2( + NamingContext.getClassNameTable(this.namingContext)) + .getText(text22)) + .length() + > 0) { + text6 = "" + text6 + "."; + } + String text7; + do { + text7 = + "" + + text6 + + ClassNameTable.getNameGenerator( + NamingContext.getClassNameTable(this.namingContext)) + .nextName(); + } while (ClassNameTable.getLookupTable( + NamingContext.getClassNameTable(this.namingContext)) + .matchesText(text7)); + stringTokenizer2 = stringTokenizer; + ClassNameTable.getLookupTable2(NamingContext.getClassNameTable(this.namingContext)) + .processText(text5, text7); + ClassNameTable.getLookupTable(NamingContext.getClassNameTable(this.namingContext)) + .processText(text7, "&"); + } + return ClassNameTable.getLookupTable2(NamingContext.getClassNameTable(this.namingContext)) + .getText(text); + } + } + } + + public boolean matchesEnabled2(ClassGen classGen, String text, String text2, boolean matches) { + if (MethodNameTable.getLookupTable3(NamingContext.getMethodNameTable(this.namingContext)) + .matchesText("" + classGen.getClassName() + "&" + text + "&" + text2)) { + return true; + } + if (!matches) { + return false; + } + int value; + Vector vector; + for (int value2 = + value = (vector = this.classHierarchy.getValues(classGen.getClassName())).size() - 1; + value2 >= 0; + value2 = --value) { + if (this.matchesEnabled2((ClassGen) vector.get(value), text, text2, matches)) { + return true; + } + } + return false; + } + + public String createText3(String text) { + if (!text.contains("$")) { + return ParameterNameTable.getLookupTable( + NamingContext.getParameterNameTable(this.namingContext)) + .getText(text); + } + String text2; + if ((text2 = + ParameterNameTable.getLookupTable( + NamingContext.getParameterNameTable(this.namingContext)) + .getText(text)) + == null) { + return this.createText3(text.substring(0, text.lastIndexOf(36))); + } + int value; + if ((value = text2.lastIndexOf(46)) != -1) { + text2 = text2.substring(value + 1); + } + int value2; + if ((value2 = text2.lastIndexOf(36)) != -1) { + text2 = text2.substring(value2 + 1); + } + return text2.charAt(0) >= '0' && text2.charAt(0) <= '9' + ? ("" + this.createText3(text.substring(0, text.lastIndexOf(36))) + '$' + '0' + text2) + : ("" + this.createText3(text.substring(0, text.lastIndexOf(36))) + '$' + text2); + } + + public void processClassGen9(ClassGen classGen) { + if (this.matchesClassGen(classGen) + || !Configuration.getRenamingOptions() + .getKeepNamesOptions() + .matchesClassGen(this.classStorage, classGen)) { + String className = classGen.getClassName(); + byte value = 0; + if (ParameterNameTable.getLookupTable(NamingContext.getParameterNameTable(this.namingContext)) + .matchesText(className) + && !className.equals( + ParameterNameTable.getLookupTable( + NamingContext.getParameterNameTable(this.namingContext)) + .getText(className))) { + value = 1; + } + if (value == 0) { + ParameterNameTable.getLookupTable(NamingContext.getParameterNameTable(this.namingContext)) + .processText(className, className); + ParameterNameTable.getLookupTable3(NamingContext.getParameterNameTable(this.namingContext)) + .processText(className, className); + String text2 = NameUtils.getText2(className); + String text; + if (Configuration.getRenamingOptions().isText2() + && (text = + ClassNameTable.getLookupTable2( + NamingContext.getClassNameTable(this.namingContext)) + .getText(text2)) + != null + && !text.equals(text2)) { + if (lookupTable.getText(text) == null) { + Log.warn("Package '" + text + "' should be un-renamed."); + } + lookupTable.processText(text, text2); + } + ClassNameTable.getLookupTable2(NamingContext.getClassNameTable(this.namingContext)) + .processText(text2, text2); + ClassNameTable.getLookupTable(NamingContext.getClassNameTable(this.namingContext)) + .processText(text2, "&"); + for (String text3 = text2; text3.lastIndexOf(46) > 0; text3 = text2) { + text2 = text2.substring(0, text2.lastIndexOf(46)); + String text4; + if (Configuration.getRenamingOptions().isText2() + && (text4 = + ClassNameTable.getLookupTable2( + NamingContext.getClassNameTable(this.namingContext)) + .getText(text2)) + != null + && !text4.equals(text2)) { + if (lookupTable.getText(text4) == null) { + Log.warn("Package '" + text4 + "' should be un-renamed."); + } + lookupTable.processText(text4, text2); + } + ClassNameTable.getLookupTable2(NamingContext.getClassNameTable(this.namingContext)) + .processText(text2, text2); + ClassNameTable.getLookupTable(NamingContext.getClassNameTable(this.namingContext)) + .processText(text2, "&"); + } + } else { + String text22 = NameUtils.getText2(className); + String text23 = + NameUtils.getText2( + ParameterNameTable.getLookupTable( + NamingContext.getParameterNameTable(this.namingContext)) + .getText(className)); + if (!Configuration.getRenamingOptions().isText() + || !text23.equals(Configuration.getRenamingOptions().getDefaultPackage())) { + if (new StringTokenizer(text22, ".").countTokens() + == new StringTokenizer(text23, ".").countTokens()) { + ClassNameTable.getLookupTable2(NamingContext.getClassNameTable(this.namingContext)) + .processText(text22, text23); + ClassNameTable.getLookupTable(NamingContext.getClassNameTable(this.namingContext)) + .processText(text23, "&"); + String text5 = text22; + while (text5.lastIndexOf(46) > 0) { + text22 = text22.substring(0, text22.lastIndexOf(46)); + text23 = text23.substring(0, text23.lastIndexOf(46)); + LookupTable lookupTable2 = + ClassNameTable.getLookupTable2( + NamingContext.getClassNameTable(this.namingContext)); + text5 = text22; + lookupTable2.processText(text22, text23); + ClassNameTable.getLookupTable(NamingContext.getClassNameTable(this.namingContext)) + .processText(text23, "&"); + } + } + } + } + } + } + + public void update7() { + Iterator iterator2; + Iterator iterator3 = iterator2 = this.classHierarchy.getValues().iterator(); + while (iterator3.hasNext()) { + ClassGen classGen = (ClassGen) iterator2.next(); + if (Configuration.getIgnoreClassesOptions().matchesClassGen(this.classStorage, classGen)) { + iterator3 = iterator2; + } else { + this.processClassGen10(classGen); + iterator3 = iterator2; + } + } + } + + public void processClassGen10(ClassGen classGen) { + if (ParameterNameTable.getLookupTable2(NamingContext.getParameterNameTable(this.namingContext)) + .matchesText(classGen.getClassName()) + || Configuration.getRenamingOptions().isForceDefaultPackageEnabled()) { + NameUtils.processAccessFlags(classGen); + } + if (Configuration.getObfuscationOptions().isFinalizeEnabled() + && !classGen.isEnabled15() + && !classGen.isEnabled5() + && !classGen.isEnabled2() + && !classGen.isEnabled10() + && this.classHierarchy.getValues(classGen.getClassName()).isEmpty()) { + classGen.processEnabled2(true); + } + String text = + ParameterNameTable.getLookupTable(NamingContext.getParameterNameTable(this.namingContext)) + .getText(classGen.getClassName()); + if (!classGen.getClassName().equals(text)) { + classGen.processText4(text); + RenameStatistics.count3++; + } + this.nameMappingEntry.processClassGen(classGen); + String[] texts; + int value = (texts = classGen.getInterfaceNames()).length; + int value2; + for (int value3 = value2 = 0; value3 < value; value3 = ++value2) { + String text2 = texts[value2]; + String text3; + if ((text3 = + ParameterNameTable.getLookupTable( + NamingContext.getParameterNameTable(this.namingContext)) + .getText(text2)) + != null) { + classGen.processText3(text2); + classGen.processText(text3); + classGen.getConstantPool().addClass(text3); + } else { + classGen.processText3(text2); + classGen.processText(text2); + } + } + this.processConstantPoolGen(classGen.getAnnotationEntries(), classGen.getConstantPool()); + } + + public boolean matchesEnabled( + ClassGen classGen, String text, String text2, boolean matches, boolean matches2) { + if (matches2) { + ClassGen classGen2 = classGen; + do { + String superclassName = classGen2.getSuperclassName(); + if ((classGen2 = this.classStorage.getClassGen(superclassName)) != null + && MethodNameTable.getLookupTable3(NamingContext.getMethodNameTable(this.namingContext)) + .matchesText("" + classGen2.getClassName() + "&" + text + "&" + text2)) { + return true; + } + } while (classGen2 != null); + } + if (MethodNameTable.getLookupTable3(NamingContext.getMethodNameTable(this.namingContext)) + .matchesText("" + classGen.getClassName() + "&" + text + "&" + text2)) { + return true; + } + if (!matches) { + return false; + } + Vector vector; + int value; + for (int value2 = + value = (vector = this.classHierarchy.getValues(classGen.getClassName())).size() - 1; + value2 >= 0; + value2 = --value) { + if (this.matchesEnabled((ClassGen) vector.get(value), text, text2, matches, matches2)) { + return true; + } + } + return false; + } +} diff --git a/src/main/java/com/allatori/naming/NameUtils.java b/src/main/java/com/allatori/naming/NameUtils.java new file mode 100644 index 0000000..25ae614 --- /dev/null +++ b/src/main/java/com/allatori/naming/NameUtils.java @@ -0,0 +1,77 @@ +package com.allatori.naming; + +import com.allatori.config.Configuration; +import com.allatori.lib.bcel.classfile.AccessFlags; +import com.allatori.lib.bcel.generic.ArrayType; +import com.allatori.lib.bcel.generic.ObjectType; +import com.allatori.lib.bcel.generic.ReferenceType; +import com.allatori.lib.bcel.generic.Type; +import com.allatori.util.LookupTable; + +public class NameUtils { + + public static String getText(String text) { + return getText4(text); + } + + public static boolean matchesAccessFlags(AccessFlags accessFlags) { + return !accessFlags.isEnabled6() && !accessFlags.isEnabled13() && !accessFlags.isEnabled9(); + } + + public static String getText2(String text) { + return getText3(text); + } + + public static boolean matchesAccessFlags2(AccessFlags accessFlags) { + return matchesAccessFlags(accessFlags); + } + + public static String getText3(String text) { + int value; + return (value = text.lastIndexOf(46)) == -1 ? "" : text.substring(0, value); + } + + public static void processAccessFlags(AccessFlags accessFlags) { + processAccessFlags2(accessFlags); + } + + public static Type getType(Type type, LookupTable lookupTable) { + return createType(type, lookupTable); + } + + public static String getText4(String text) { + return !Configuration.getRenamingOptions().isCompatibleRenamingEnabled() + && !Configuration.getRenamingOptions().isEnabled8() + ? text + : text.substring(0, text.lastIndexOf(41)); + } + + public static void processAccessFlags2(AccessFlags accessFlags) { + accessFlags.processEnabled5(false); + accessFlags.processEnabled7(false); + accessFlags.processEnabled13(true); + } + + public static Type createType(Type type, LookupTable lookupTable) { + ReferenceType referenceType = null; + if (type instanceof ObjectType) { + String className = ((ObjectType) type).getClassName(); + String text; + if ((text = lookupTable.getText(className)) != null && !text.equals(className)) { + referenceType = new ObjectType(text); + } + } else { + Type type2; + ArrayType arrayType; + if (type instanceof ArrayType + && (type2 = (arrayType = (ArrayType) type).getBasicType()) instanceof ObjectType) { + String className2 = ((ObjectType) type2).getClassName(); + String text2; + if ((text2 = lookupTable.getText(className2)) != null && !text2.equals(className2)) { + referenceType = new ArrayType(text2, arrayType.getDimensions()); + } + } + } + return referenceType; + } +} diff --git a/src/main/java/com/allatori/naming/NamingConstructorToken.java b/src/main/java/com/allatori/naming/NamingConstructorToken.java new file mode 100644 index 0000000..8e3494c --- /dev/null +++ b/src/main/java/com/allatori/naming/NamingConstructorToken.java @@ -0,0 +1,3 @@ +package com.allatori.naming; + +public class NamingConstructorToken {} diff --git a/src/main/java/com/allatori/naming/NamingContext.java b/src/main/java/com/allatori/naming/NamingContext.java new file mode 100644 index 0000000..d71233d --- /dev/null +++ b/src/main/java/com/allatori/naming/NamingContext.java @@ -0,0 +1,50 @@ +package com.allatori.naming; + +public class NamingContext { + + public PackageNameTable packageNameTable; + + public MethodNameTable methodNameTable; + + public ParameterNameTable parameterNameTable; + + public FieldNameTable fieldNameTable; + + public final NameRenamer nameRenamer; + + public ClassNameTable classNameTable; + + public static MethodNameTable getMethodNameTable(NamingContext namingContext) { + return namingContext.methodNameTable; + } + + public NamingContext(NameRenamer nameRenamer, NamingConstructorToken namingConstructorToken) { + this(nameRenamer); + } + + public static ParameterNameTable getParameterNameTable(NamingContext namingContext) { + return namingContext.parameterNameTable; + } + + public static ClassNameTable getClassNameTable(NamingContext namingContext) { + return namingContext.classNameTable; + } + + public static PackageNameTable getPackageNameTable(NamingContext namingContext) { + return namingContext.packageNameTable; + } + + public NamingContext(NameRenamer nameRenamer2) { + super(); + this.nameRenamer = nameRenamer2; + this.classNameTable = new ClassNameTable(this, null); + this.parameterNameTable = new ParameterNameTable(this, null); + this.methodNameTable = new MethodNameTable(this, null); + this.fieldNameTable = new FieldNameTable(this, null); + this.packageNameTable = new PackageNameTable(this, null); + } + + public static FieldNameTable getFieldNameTable(NamingContext namingContext) { + return namingContext.fieldNameTable; + } +} diff --git a/src/main/java/com/allatori/naming/PackageNameTable.java b/src/main/java/com/allatori/naming/PackageNameTable.java new file mode 100644 index 0000000..68f6cf5 --- /dev/null +++ b/src/main/java/com/allatori/naming/PackageNameTable.java @@ -0,0 +1,27 @@ +package com.allatori.naming; + +import com.allatori.config.Configuration; +import com.allatori.naming.generator.NameGenerator; + +public class PackageNameTable { + + public final NamingContext namingContext; + + public NameGenerator nameGenerator; + + public static NameGenerator getNameGenerator(PackageNameTable packageNameTable) { + return packageNameTable.nameGenerator; + } + + public PackageNameTable(NamingContext namingContext2) { + super(); + this.namingContext = namingContext2; + this.nameGenerator = + Configuration.getRenamingOptions().getNameGenerationOptions().createNameGenerator3(); + } + + public PackageNameTable( + NamingContext namingContext, NamingConstructorToken namingConstructorToken) { + this(namingContext); + } +} diff --git a/src/main/java/com/allatori/naming/ParameterNameTable.java b/src/main/java/com/allatori/naming/ParameterNameTable.java new file mode 100644 index 0000000..ceb2ab6 --- /dev/null +++ b/src/main/java/com/allatori/naming/ParameterNameTable.java @@ -0,0 +1,49 @@ +package com.allatori.naming; + +import com.allatori.config.Configuration; +import com.allatori.naming.generator.NameGenerator; +import com.allatori.util.LookupTable; + +public class ParameterNameTable { + + public LookupTable lookupTable; + + public LookupTable lookupTable2; + + public LookupTable lookupTable3; + + public NameGenerator nameGenerator; + + public final NamingContext namingContext; + + public ParameterNameTable(NamingContext namingContext2) { + super(); + this.namingContext = namingContext2; + this.nameGenerator = + Configuration.getRenamingOptions().getNameGenerationOptions().createNameGenerator6(); + this.lookupTable = new LookupTable(); + this.lookupTable3 = new LookupTable(); + this.lookupTable2 = new LookupTable(); + } + + public static LookupTable getLookupTable(ParameterNameTable parameterNameTable) { + return parameterNameTable.lookupTable; + } + + public static LookupTable getLookupTable2(ParameterNameTable parameterNameTable) { + return parameterNameTable.lookupTable2; + } + + public ParameterNameTable( + NamingContext namingContext, NamingConstructorToken namingConstructorToken) { + this(namingContext); + } + + public static NameGenerator getNameGenerator(ParameterNameTable parameterNameTable) { + return parameterNameTable.nameGenerator; + } + + public static LookupTable getLookupTable3(ParameterNameTable parameterNameTable) { + return parameterNameTable.lookupTable3; + } +} diff --git a/src/main/java/com/allatori/naming/RenameStatistics.java b/src/main/java/com/allatori/naming/RenameStatistics.java new file mode 100644 index 0000000..1c5f4fd --- /dev/null +++ b/src/main/java/com/allatori/naming/RenameStatistics.java @@ -0,0 +1,10 @@ +package com.allatori.naming; + +public class RenameStatistics { + + public static int count; + + public static int count2; + + public static int count3; +} diff --git a/src/main/java/com/allatori/naming/RenamingLog.java b/src/main/java/com/allatori/naming/RenamingLog.java new file mode 100644 index 0000000..d975664 --- /dev/null +++ b/src/main/java/com/allatori/naming/RenamingLog.java @@ -0,0 +1,39 @@ +package com.allatori.naming; + +import com.allatori.util.LookupTable; +import java.util.Vector; + +public class RenamingLog { + + public LookupTable lookupTable; + + public LookupTable lookupTable2; + + public Vector values; + + public LookupTable lookupTable3; + + public LookupTable lookupTable4; + + public LookupTable lookupTable5; + + public Vector values2; + + public RenamingLog( + LookupTable lookupTable6, + LookupTable lookupTable7, + LookupTable lookupTable8, + Vector vector, + Vector vector2, + LookupTable lookupTable9, + LookupTable lookupTable10) { + super(); + this.lookupTable4 = lookupTable6; + this.lookupTable5 = lookupTable7; + this.lookupTable2 = lookupTable8; + this.values2 = vector; + this.values = vector2; + this.lookupTable3 = lookupTable9; + this.lookupTable = lookupTable10; + } +} diff --git a/src/main/java/com/allatori/naming/generator/AsciiNameGenerator.java b/src/main/java/com/allatori/naming/generator/AsciiNameGenerator.java new file mode 100644 index 0000000..835eff3 --- /dev/null +++ b/src/main/java/com/allatori/naming/generator/AsciiNameGenerator.java @@ -0,0 +1,39 @@ +package com.allatori.naming.generator; + +public class AsciiNameGenerator implements NameGenerator { + + public long seed = 0L; + + public static String text = "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ"; + + public static int count = text.length(); + + @Override + public String nextName() { + String text2 = ""; + long value = this.seed; + int value2 = 1; + long value3 = count; + for (long value4 = value; value4 >= value3; value4 = value) { + long value5 = value; + value2++; + value = value5 - value3; + value3 *= count; + } + int value6; + for (int value7 = value6 = 0; value7 < value2; value7 = value6) { + text2 = "" + text2 + text.charAt((int) (value % count)); + int value8 = count; + long value9 = value; + value6++; + value = value9 / value8; + } + this.seed++; + return text2; + } + + @Override + public void reset() { + this.seed = 0L; + } +} diff --git a/src/main/java/com/allatori/naming/generator/DictionaryNameGenerator.java b/src/main/java/com/allatori/naming/generator/DictionaryNameGenerator.java new file mode 100644 index 0000000..1b98339 --- /dev/null +++ b/src/main/java/com/allatori/naming/generator/DictionaryNameGenerator.java @@ -0,0 +1,30 @@ +package com.allatori.naming.generator; + +public class DictionaryNameGenerator implements NameGenerator { + + public AsciiNameGenerator asciiNameGenerator; + + public int count; + + public String[] texts; + + @Override + public String nextName() { + return this.count < this.texts.length + ? this.texts[this.count++] + : this.asciiNameGenerator.nextName(); + } + + public DictionaryNameGenerator(String[] texts2) { + super(); + this.asciiNameGenerator = new AsciiNameGenerator(); + this.count = 0; + this.texts = texts2; + } + + @Override + public void reset() { + this.count = 0; + this.asciiNameGenerator.reset(); + } +} diff --git a/src/main/java/com/allatori/naming/generator/JavaKeywordNameGenerator.java b/src/main/java/com/allatori/naming/generator/JavaKeywordNameGenerator.java new file mode 100644 index 0000000..bb7d07e --- /dev/null +++ b/src/main/java/com/allatori/naming/generator/JavaKeywordNameGenerator.java @@ -0,0 +1,72 @@ +package com.allatori.naming.generator; + +import com.allatori.naming.NameComparator; +import java.util.Arrays; + +public class JavaKeywordNameGenerator extends DictionaryNameGenerator { + + public static String[] texts = + new String[] { + "abstract", + "assert", + "boolean", + "break", + "byte", + "case", + "catch", + "char", + "class", + "const", + "continue", + "default", + "do", + "double", + "else", + "enum", + "extends", + "false", + "final", + "finally", + "float", + "for", + "goto", + "if", + "implements", + "import", + "instanceof", + "int", + "interface", + "long", + "native", + "new", + "null", + "package", + "private", + "protected", + "public", + "return", + "short", + "static", + "strictfp", + "super", + "switch", + "synchronized", + "this", + "throw", + "throws", + "transient", + "true", + "try", + "void", + "volatile", + "while" + }; + + static { + Arrays.sort(texts, new NameComparator()); + } + + public JavaKeywordNameGenerator() { + super(texts); + } +} diff --git a/src/main/java/com/allatori/naming/generator/LengthBoundNameGenerator.java b/src/main/java/com/allatori/naming/generator/LengthBoundNameGenerator.java new file mode 100644 index 0000000..38c4fb9 --- /dev/null +++ b/src/main/java/com/allatori/naming/generator/LengthBoundNameGenerator.java @@ -0,0 +1,74 @@ +package com.allatori.naming.generator; + +import com.allatori.config.Configuration; +import com.allatori.util.random.RandomUtils; +import java.util.Vector; + +public class LengthBoundNameGenerator implements NameGenerator { + + public int count; + + public int count2; + + public NameGenerator nameGenerator; + + public Vector values; + + public boolean enabled; + + public boolean enabled2; + + public Vector values2; + + @Override + public void reset() { + this.count = 0; + } + + public LengthBoundNameGenerator(NameGenerator nameGenerator2) { + super(); + this.values = new Vector(); + this.count = 0; + this.values2 = new Vector(); + this.count2 = 26; + this.enabled2 = false; + this.enabled = false; + this.nameGenerator = nameGenerator2; + if (nameGenerator2 instanceof MixedConfusableNameGenerator) { + this.enabled2 = true; + this.count2 = 1024; + } + if (nameGenerator2 instanceof LowercaseConfusableNameGenerator) { + this.enabled = true; + this.count2 = 1024; + } + } + + @Override + public String nextName() { + if (this.count < this.values.size()) { + return (String) this.values.get(this.count++); + } + if (!this.enabled2 && this.values.size() == 104) { + this.count2 = 299; + } + int value; + for (int value2 = value = 0; value2 < this.count2; value2 = value) { + Vector vector = this.values2; + value++; + vector.add(this.nameGenerator.nextName()); + } + if (Configuration.getRenamingOptions().isRandomizeNamesEnabled()) { + RandomUtils.processValues(this.values2); + } + this.values.addAll(this.values2); + this.values2.clear(); + if (this.enabled2) { + MixedConfusableNameGenerator.setText((String) this.values.get(0)); + } + if (this.enabled) { + LowercaseConfusableNameGenerator.setText((String) this.values.get(0)); + } + return (String) this.values.get(this.count++); + } +} diff --git a/src/main/java/com/allatori/naming/generator/LowercaseConfusableNameGenerator.java b/src/main/java/com/allatori/naming/generator/LowercaseConfusableNameGenerator.java new file mode 100644 index 0000000..f745c4c --- /dev/null +++ b/src/main/java/com/allatori/naming/generator/LowercaseConfusableNameGenerator.java @@ -0,0 +1,48 @@ +package com.allatori.naming.generator; + +public class LowercaseConfusableNameGenerator implements NameGenerator { + + public static int count = 10; + + public static String text = "l11l1l11l1"; + + public long seed = 0L; + + @Override + public String nextName() { + String text; + String text2 = text = Long.toBinaryString(this.seed++); + while (text2.length() < count) { + text2 = text = '0' + text; + } + StringBuffer stringBuffer = new StringBuffer(text.length()); + int value; + for (int value2 = value = 0; value2 < text.length(); value2 = ++value) { + if (value % 2 == 0) { + stringBuffer.append((char) (text.charAt(value) == '0' ? '1' : 'l')); + } else { + stringBuffer.insert(0, (char) (text.charAt(value) == '0' ? '1' : 'l')); + } + } + return stringBuffer.insert(0, 'l').toString(); + } + + public static void processCount(int value) { + if (value - 1 > count) { + count = value - 1; + } + } + + public static void setText(String text2) { + text = text2; + } + + @Override + public void reset() { + this.seed = 0L; + } + + public static String nextName2() { + return text; + } +} diff --git a/src/main/java/com/allatori/naming/generator/LowercaseNameGenerator.java b/src/main/java/com/allatori/naming/generator/LowercaseNameGenerator.java new file mode 100644 index 0000000..6b14fec --- /dev/null +++ b/src/main/java/com/allatori/naming/generator/LowercaseNameGenerator.java @@ -0,0 +1,38 @@ +package com.allatori.naming.generator; + +public class LowercaseNameGenerator implements NameGenerator { + + public static final int COUNT = 26; + + public static String text = "abcdefghijklmnopqrstuvwxyz"; + + public long seed = 0L; + + @Override + public String nextName() { + String text2 = ""; + long value = this.seed; + int value2 = 1; + long value3 = 26L; + for (long value4 = value; value4 >= value3; value4 = value) { + long value5 = value; + value2++; + value = value5 - value3; + value3 *= 26L; + } + int value6; + for (int value7 = value6 = 0; value7 < value2; value7 = value6) { + text2 = "" + text2 + text.charAt((int) (value % 26L)); + long value8 = value; + value6++; + value = value8 / 26L; + } + this.seed++; + return text2; + } + + @Override + public void reset() { + this.seed = 0L; + } +} diff --git a/src/main/java/com/allatori/naming/generator/MainNameGenerator.java b/src/main/java/com/allatori/naming/generator/MainNameGenerator.java new file mode 100644 index 0000000..130fbe2 --- /dev/null +++ b/src/main/java/com/allatori/naming/generator/MainNameGenerator.java @@ -0,0 +1,62 @@ +package com.allatori.naming.generator; + +import java.util.Vector; + +public class MainNameGenerator implements NameGenerator { + + public boolean enabled; + + public boolean enabled2; + + public static Vector values = new Vector(); + + public NameGenerator nameGenerator; + + public static Vector values2 = new Vector(); + + public int count; + + public static void processText(String text) { + if (text.charAt(0) != '<' && !"main".equals(text)) { + if (!values2.contains(text)) { + values2.add(text); + } + } + } + + @Override + public void reset() { + this.count = 0; + this.nameGenerator.reset(); + } + + public static void reset2() { + values = new Vector(); + values2 = new Vector(); + } + + public static void processText2(String text) { + if (!values.contains(text)) { + values.add(text); + } + } + + public MainNameGenerator(NameGenerator nameGenerator2, boolean enabled2, boolean enabled) { + super(); + this.count = 0; + this.nameGenerator = nameGenerator2; + this.enabled2 = enabled2; + this.enabled = enabled; + } + + @Override + public String nextName() { + if (this.enabled2 && this.count < values.size()) { + return (String) values.get(this.count++); + } else { + return this.enabled && this.count < values2.size() + ? (String) values2.get(this.count++) + : this.nameGenerator.nextName(); + } + } +} diff --git a/src/main/java/com/allatori/naming/generator/MemberNameGenerator.java b/src/main/java/com/allatori/naming/generator/MemberNameGenerator.java new file mode 100644 index 0000000..1302535 --- /dev/null +++ b/src/main/java/com/allatori/naming/generator/MemberNameGenerator.java @@ -0,0 +1,24 @@ +package com.allatori.naming.generator; + +public class MemberNameGenerator implements NameGenerator { + + public long seed; + + public String text; + + @Override + public String nextName() { + return "" + this.text + (this.seed++); + } + + @Override + public void reset() { + this.seed = 0L; + } + + public MemberNameGenerator(String text) { + super(); + this.seed = 0L; + this.text = text; + } +} diff --git a/src/main/java/com/allatori/naming/generator/MethodNameGenerator.java b/src/main/java/com/allatori/naming/generator/MethodNameGenerator.java new file mode 100644 index 0000000..8307651 --- /dev/null +++ b/src/main/java/com/allatori/naming/generator/MethodNameGenerator.java @@ -0,0 +1,28 @@ +package com.allatori.naming.generator; + +public class MethodNameGenerator implements NameGenerator { + + public NameGenerator nameGenerator; + + public String text; + + public int count; + + @Override + public String nextName() { + return this.count++ == 0 ? this.text : this.nameGenerator.nextName(); + } + + public MethodNameGenerator(String text, NameGenerator nameGenerator2) { + super(); + this.count = 0; + this.text = text; + this.nameGenerator = nameGenerator2; + } + + @Override + public void reset() { + this.count = 0; + this.nameGenerator.reset(); + } +} diff --git a/src/main/java/com/allatori/naming/generator/MixedConfusableNameGenerator.java b/src/main/java/com/allatori/naming/generator/MixedConfusableNameGenerator.java new file mode 100644 index 0000000..f8a2c3c --- /dev/null +++ b/src/main/java/com/allatori/naming/generator/MixedConfusableNameGenerator.java @@ -0,0 +1,48 @@ +package com.allatori.naming.generator; + +public class MixedConfusableNameGenerator implements NameGenerator { + + public static int count = 10; + + public static String text = "IiiIiIiiII"; + + public long seed = 0L; + + public static void processCount(int value) { + if (value > count) { + count = value; + } + } + + public static String nextName2() { + return text; + } + + @Override + public void reset() { + this.seed = 0L; + } + + @Override + public String nextName() { + String text; + String text2 = text = Long.toBinaryString(this.seed++); + while (text2.length() < count) { + text2 = text = '0' + text; + } + StringBuffer stringBuffer = new StringBuffer(text.length()); + int value; + for (int value2 = value = 0; value2 < text.length(); value2 = ++value) { + if (value % 2 == 0) { + stringBuffer.append((char) (text.charAt(value) == '0' ? 'i' : 'I')); + } else { + stringBuffer.insert(0, (char) (text.charAt(value) == '0' ? 'i' : 'I')); + } + } + return stringBuffer.toString(); + } + + public static void setText(String text2) { + text = text2; + } +} diff --git a/src/main/java/com/allatori/naming/generator/NameGenerator.java b/src/main/java/com/allatori/naming/generator/NameGenerator.java new file mode 100644 index 0000000..1761d16 --- /dev/null +++ b/src/main/java/com/allatori/naming/generator/NameGenerator.java @@ -0,0 +1,8 @@ +package com.allatori.naming.generator; + +public interface NameGenerator { + + String nextName(); + + void reset(); +} diff --git a/src/main/java/com/allatori/naming/generator/NumericNameGenerator.java b/src/main/java/com/allatori/naming/generator/NumericNameGenerator.java new file mode 100644 index 0000000..3cbbee3 --- /dev/null +++ b/src/main/java/com/allatori/naming/generator/NumericNameGenerator.java @@ -0,0 +1,38 @@ +package com.allatori.naming.generator; + +public class NumericNameGenerator implements NameGenerator { + + public static String text = "0123456789"; + + public long seed = 0L; + + public static final int COUNT = 10; + + @Override + public void reset() { + this.seed = 0L; + } + + @Override + public String nextName() { + String text2 = ""; + long value = this.seed; + int value2 = 1; + long value3 = 10L; + for (long value4 = value; value4 >= value3; value4 = value) { + long value5 = value; + value2++; + value = value5 - value3; + value3 *= 10L; + } + int value6; + for (int value7 = value6 = 0; value7 < value2; value7 = value6) { + text2 = "" + text2 + text.charAt((int) (value % 10L)); + long value8 = value; + value6++; + value = value8 / 10L; + } + this.seed++; + return text2; + } +} diff --git a/src/main/java/com/allatori/naming/generator/PackageNameGenerator.java b/src/main/java/com/allatori/naming/generator/PackageNameGenerator.java new file mode 100644 index 0000000..e7b7abb --- /dev/null +++ b/src/main/java/com/allatori/naming/generator/PackageNameGenerator.java @@ -0,0 +1,46 @@ +package com.allatori.naming.generator; + +public class PackageNameGenerator implements NameGenerator { + + public String[] texts; + + public int count; + + public long seed; + + @Override + public String nextName() { + String text = ""; + long value = this.seed; + int value2 = 1; + long value3 = this.count; + for (long value4 = value; value4 >= value3; value4 = value) { + long value5 = value; + value2++; + value = value5 - value3; + value3 *= this.count; + } + int value6; + for (int value7 = value6 = 0; value7 < value2; value7 = value6) { + text = "" + text + this.texts[(int) (value % this.count)]; + int value8 = this.count; + long value9 = value; + value6++; + value = value9 / value8; + } + this.seed++; + return text; + } + + public PackageNameGenerator(String[] texts2) { + super(); + this.seed = 0L; + this.texts = texts2; + this.count = texts2.length; + } + + @Override + public void reset() { + this.seed = 0L; + } +} diff --git a/src/main/java/com/allatori/naming/generator/PrefixedNameGenerator.java b/src/main/java/com/allatori/naming/generator/PrefixedNameGenerator.java new file mode 100644 index 0000000..5826ab6 --- /dev/null +++ b/src/main/java/com/allatori/naming/generator/PrefixedNameGenerator.java @@ -0,0 +1,19 @@ +package com.allatori.naming.generator; + +public class PrefixedNameGenerator implements NameGenerator { + + public String text; + + @Override + public void reset() {} + + @Override + public String nextName() { + return this.text; + } + + public PrefixedNameGenerator(String text) { + super(); + this.text = text; + } +} diff --git a/src/main/java/com/allatori/naming/generator/RandomizedNameGenerator.java b/src/main/java/com/allatori/naming/generator/RandomizedNameGenerator.java new file mode 100644 index 0000000..46d8b09 --- /dev/null +++ b/src/main/java/com/allatori/naming/generator/RandomizedNameGenerator.java @@ -0,0 +1,22 @@ +package com.allatori.naming.generator; + +public class RandomizedNameGenerator implements NameGenerator { + + public NameGenerator nameGenerator; + + @Override + public String nextName() { + String text = this.nameGenerator.nextName(); + return !"r".equals(text) && !"R".equals(text) ? text : this.nextName(); + } + + @Override + public void reset() { + this.nameGenerator.reset(); + } + + public RandomizedNameGenerator(NameGenerator nameGenerator2) { + super(); + this.nameGenerator = nameGenerator2; + } +} diff --git a/src/main/java/com/allatori/naming/generator/TypeNameGenerator.java b/src/main/java/com/allatori/naming/generator/TypeNameGenerator.java new file mode 100644 index 0000000..7399409 --- /dev/null +++ b/src/main/java/com/allatori/naming/generator/TypeNameGenerator.java @@ -0,0 +1,24 @@ +package com.allatori.naming.generator; + +public class TypeNameGenerator implements NameGenerator { + + public String text; + + public NameGenerator nameGenerator; + + public TypeNameGenerator(String text, NameGenerator nameGenerator2) { + super(); + this.nameGenerator = nameGenerator2; + this.text = text; + } + + @Override + public String nextName() { + return "" + this.text + this.nameGenerator.nextName(); + } + + @Override + public void reset() { + this.nameGenerator.reset(); + } +} diff --git a/src/main/java/com/allatori/naming/generator/UppercaseNameGenerator.java b/src/main/java/com/allatori/naming/generator/UppercaseNameGenerator.java new file mode 100644 index 0000000..0410819 --- /dev/null +++ b/src/main/java/com/allatori/naming/generator/UppercaseNameGenerator.java @@ -0,0 +1,38 @@ +package com.allatori.naming.generator; + +public class UppercaseNameGenerator implements NameGenerator { + + public static final int COUNT = 26; + + public static String text = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + public long seed = 0L; + + @Override + public void reset() { + this.seed = 0L; + } + + @Override + public String nextName() { + String text2 = ""; + long value = this.seed; + int value2 = 1; + long value3 = 26L; + for (long value4 = value; value4 >= value3; value4 = value) { + long value5 = value; + value2++; + value = value5 - value3; + value3 *= 26L; + } + int value6; + for (int value7 = value6 = 0; value7 < value2; value7 = value6) { + text2 = "" + text2 + text.charAt((int) (value % 26L)); + long value8 = value; + value6++; + value = value8 / 26L; + } + this.seed++; + return text2; + } +} diff --git a/src/main/java/com/allatori/naming/generator/WindowsDeviceNameGenerator.java b/src/main/java/com/allatori/naming/generator/WindowsDeviceNameGenerator.java new file mode 100644 index 0000000..3726bae --- /dev/null +++ b/src/main/java/com/allatori/naming/generator/WindowsDeviceNameGenerator.java @@ -0,0 +1,35 @@ +package com.allatori.naming.generator; + +import com.allatori.naming.NameLengthComparator; +import java.util.Arrays; + +public class WindowsDeviceNameGenerator extends DictionaryNameGenerator { + + public static String[] texts = + new String[] { + "aux", "Aux", "aUx", "AUx", "auX", "AuX", "aUX", "AUX", "con", "Con", "cOn", "COn", "coN", + "CoN", "cON", "CON", "nul", "Nul", "nUl", "NUl", "nuL", "NuL", "nUL", "NUL", "prn", "Prn", + "pRn", "PRn", "prN", "PrN", "pRN", "PRN", "com1", "Com1", "cOm1", "COm1", "coM1", "CoM1", + "cOM1", "COM1", "com2", "Com2", "cOm2", "COm2", "coM2", "CoM2", "cOM2", "COM2", "com3", + "Com3", "cOm3", "COm3", "coM3", "CoM3", "cOM3", "COM3", "com4", "Com4", "cOm4", "COm4", + "coM4", "CoM4", "cOM4", "COM4", "com5", "Com5", "cOm5", "COm5", "coM5", "CoM5", "cOM5", + "COM5", "com6", "Com6", "cOm6", "COm6", "coM6", "CoM6", "cOM6", "COM6", "com7", "Com7", + "cOm7", "COm7", "coM7", "CoM7", "cOM7", "COM7", "com8", "Com8", "cOm8", "COm8", "coM8", + "CoM8", "cOM8", "COM8", "com9", "Com9", "cOm9", "COm9", "coM9", "CoM9", "cOM9", "COM9", + "lpt1", "Lpt1", "lPt1", "LPt1", "lpT1", "LpT1", "lPT1", "LPT1", "lpt2", "Lpt2", "lPt2", + "LPt2", "lpT2", "LpT2", "lPT2", "LPT2", "lpt3", "Lpt3", "lPt3", "LPt3", "lpT3", "LpT3", + "lPT3", "LPT3", "lpt4", "Lpt4", "lPt4", "LPt4", "lpT4", "LpT4", "lPT4", "LPT4", "lpt5", + "Lpt5", "lPt5", "LPt5", "lpT5", "LpT5", "lPT5", "LPT5", "lpt6", "Lpt6", "lPt6", "LPt6", + "lpT6", "LpT6", "lPT6", "LPT6", "lpt7", "Lpt7", "lPt7", "LPt7", "lpT7", "LpT7", "lPT7", + "LPT7", "lpt8", "Lpt8", "lPt8", "LPt8", "lpT8", "LpT8", "lPT8", "LPT8", "lpt9", "Lpt9", + "lPt9", "LPt9", "lpT9", "LpT9", "lPT9", "LPT9" + }; + + public WindowsDeviceNameGenerator() { + super(texts); + } + + static { + Arrays.sort(texts, new NameLengthComparator()); + } +} diff --git a/src/main/java/com/allatori/optimizer/ClassUpdateObserver.java b/src/main/java/com/allatori/optimizer/ClassUpdateObserver.java new file mode 100644 index 0000000..75befa7 --- /dev/null +++ b/src/main/java/com/allatori/optimizer/ClassUpdateObserver.java @@ -0,0 +1,10 @@ +package com.allatori.optimizer; + +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.lib.bcel.generic.ClassObserver; + +public class ClassUpdateObserver implements ClassObserver { + + @Override + public void notify(ClassGen classGen) {} +} diff --git a/src/main/java/com/allatori/optimizer/ControlFlowOptimizer.java b/src/main/java/com/allatori/optimizer/ControlFlowOptimizer.java new file mode 100644 index 0000000..2d735a7 --- /dev/null +++ b/src/main/java/com/allatori/optimizer/ControlFlowOptimizer.java @@ -0,0 +1,66 @@ +package com.allatori.optimizer; + +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.lib.bcel.generic.ClassObserver; +import com.allatori.lib.bcel.generic.InstructionList; +import com.allatori.lib.bcel.generic.MethodGen; + +public class ControlFlowOptimizer implements ClassObserver { + + @Override + public void notify(ClassGen classGen) {} + + public void processInstructionList( + ClassGen classGen, MethodGen methodGen, InstructionList instructionList) {} + + public void processInstructionList2( + ClassGen classGen, MethodGen methodGen, InstructionList instructionList) {} + + public void processInstructionList3( + ClassGen classGen, MethodGen methodGen, InstructionList instructionList) {} + + public void processInstructionList4( + ClassGen classGen, MethodGen methodGen, InstructionList instructionList) {} + + public void processInstructionList5( + ClassGen classGen, MethodGen methodGen, InstructionList instructionList) {} + + public void processInstructionList6( + ClassGen classGen, MethodGen methodGen, InstructionList instructionList) {} + + public void processInstructionList7( + ClassGen classGen, MethodGen methodGen, InstructionList instructionList) {} + + public void processEnabled( + ClassGen classGen, MethodGen methodGen, InstructionList instructionList, boolean matches) {} + + public void processInstructionList8( + ClassGen classGen, MethodGen methodGen, InstructionList instructionList) {} + + public void processInstructionList9( + ClassGen classGen, MethodGen methodGen, InstructionList instructionList) {} + + public void processInstructionList10( + ClassGen classGen, MethodGen methodGen, InstructionList instructionList) {} + + public void processInstructionList11( + ClassGen classGen, MethodGen methodGen, InstructionList instructionList) {} + + public void processInstructionList12( + ClassGen classGen, MethodGen methodGen, InstructionList instructionList) {} + + public void processInstructionList13( + ClassGen classGen, MethodGen methodGen, InstructionList instructionList) {} + + public void processEnabled2( + ClassGen classGen, MethodGen methodGen, InstructionList instructionList, boolean matches) {} + + public void processInstructionList14( + ClassGen classGen, MethodGen methodGen, InstructionList instructionList) {} + + public void processInstructionList15( + ClassGen classGen, MethodGen methodGen, InstructionList instructionList) {} + + public void processInstructionList16( + ClassGen classGen, MethodGen methodGen, InstructionList instructionList) {} +} diff --git a/src/main/java/com/allatori/optimizer/MethodOptimizer.java b/src/main/java/com/allatori/optimizer/MethodOptimizer.java new file mode 100644 index 0000000..38e81fb --- /dev/null +++ b/src/main/java/com/allatori/optimizer/MethodOptimizer.java @@ -0,0 +1,4817 @@ +package com.allatori.optimizer; + +import com.allatori.bytecode.MethodFactory; +import com.allatori.config.Configuration; +import com.allatori.lib.bcel.classfile.Method; +import com.allatori.lib.bcel.generic.ACONST_NULL; +import com.allatori.lib.bcel.generic.ALOAD; +import com.allatori.lib.bcel.generic.ANEWARRAY; +import com.allatori.lib.bcel.generic.ASTORE; +import com.allatori.lib.bcel.generic.ATHROW; +import com.allatori.lib.bcel.generic.ArithmeticInstruction; +import com.allatori.lib.bcel.generic.ArrayInstruction; +import com.allatori.lib.bcel.generic.ArrayType; +import com.allatori.lib.bcel.generic.BIPUSH; +import com.allatori.lib.bcel.generic.BranchInstruction; +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.lib.bcel.generic.ClassGenException; +import com.allatori.lib.bcel.generic.ClassObserver; +import com.allatori.lib.bcel.generic.CodeExceptionGen; +import com.allatori.lib.bcel.generic.ConstantPoolGen; +import com.allatori.lib.bcel.generic.ConstantPushInstruction; +import com.allatori.lib.bcel.generic.ConversionInstruction; +import com.allatori.lib.bcel.generic.DCONST; +import com.allatori.lib.bcel.generic.DLOAD; +import com.allatori.lib.bcel.generic.DSTORE; +import com.allatori.lib.bcel.generic.DUP; +import com.allatori.lib.bcel.generic.FCONST; +import com.allatori.lib.bcel.generic.FLOAD; +import com.allatori.lib.bcel.generic.FSTORE; +import com.allatori.lib.bcel.generic.FieldInstruction; +import com.allatori.lib.bcel.generic.FieldOrMethod; +import com.allatori.lib.bcel.generic.GETFIELD; +import com.allatori.lib.bcel.generic.GETSTATIC; +import com.allatori.lib.bcel.generic.GOTO; +import com.allatori.lib.bcel.generic.GotoInstruction; +import com.allatori.lib.bcel.generic.ICONST; +import com.allatori.lib.bcel.generic.IFNE; +import com.allatori.lib.bcel.generic.IINC; +import com.allatori.lib.bcel.generic.ILOAD; +import com.allatori.lib.bcel.generic.INVOKESPECIAL; +import com.allatori.lib.bcel.generic.INVOKEVIRTUAL; +import com.allatori.lib.bcel.generic.ISTORE; +import com.allatori.lib.bcel.generic.IfInstruction; +import com.allatori.lib.bcel.generic.Instruction; +import com.allatori.lib.bcel.generic.InstructionConstants; +import com.allatori.lib.bcel.generic.InstructionFactory; +import com.allatori.lib.bcel.generic.InstructionHandle; +import com.allatori.lib.bcel.generic.InstructionList; +import com.allatori.lib.bcel.generic.InstructionTargeter; +import com.allatori.lib.bcel.generic.InvokeInstruction; +import com.allatori.lib.bcel.generic.LCONST; +import com.allatori.lib.bcel.generic.LDC; +import com.allatori.lib.bcel.generic.LDC2_W; +import com.allatori.lib.bcel.generic.LLOAD; +import com.allatori.lib.bcel.generic.LSTORE; +import com.allatori.lib.bcel.generic.LineNumberGen; +import com.allatori.lib.bcel.generic.LoadInstruction; +import com.allatori.lib.bcel.generic.LocalVariableGen; +import com.allatori.lib.bcel.generic.LocalVariableInstruction; +import com.allatori.lib.bcel.generic.MethodGen; +import com.allatori.lib.bcel.generic.NEW; +import com.allatori.lib.bcel.generic.NEWARRAY; +import com.allatori.lib.bcel.generic.NOP; +import com.allatori.lib.bcel.generic.ObjectType; +import com.allatori.lib.bcel.generic.POP; +import com.allatori.lib.bcel.generic.POP2; +import com.allatori.lib.bcel.generic.PUSH; +import com.allatori.lib.bcel.generic.PopInstruction; +import com.allatori.lib.bcel.generic.PushInstruction; +import com.allatori.lib.bcel.generic.RET; +import com.allatori.lib.bcel.generic.ReturnInstruction; +import com.allatori.lib.bcel.generic.Select; +import com.allatori.lib.bcel.generic.StoreInstruction; +import com.allatori.lib.bcel.generic.TargetLostException; +import com.allatori.lib.bcel.generic.Type; +import com.allatori.model.ClassStorage; +import com.allatori.util.Log; +import com.allatori.util.random.RandomUtils; +import java.util.Arrays; +import java.util.Hashtable; +import java.util.Vector; + +public class MethodOptimizer implements ClassObserver { + + public ClassStorage classStorage; + + public void processInstructionList( + ClassGen classGen, MethodGen methodGen, InstructionList instructionList) { + int value; + int value2; + InstructionHandle instructionHandle; + InstructionHandle instructionHandle2 = instructionHandle = instructionList.getStart(); + while (instructionHandle2 != null) { + if (!this.matchesInstruction(instructionHandle.getInstruction())) { + instructionHandle2 = instructionHandle; + } else { + int value3 = 1; + InstructionHandle instructionHandle3; + instructionHandle2 = instructionHandle3 = instructionHandle.getInstructionHandle2(); + while (true) { + if (instructionHandle2 == null) { + value2 = value3; + break; + } + if (!this.matchesInstruction(instructionHandle3.getInstruction())) { + value2 = value3; + break; + } + if (!this.matchesConstantPoolGen( + instructionHandle3.getInstruction(), + instructionHandle.getInstruction(), + classGen.getConstantPool())) { + value2 = value3; + break; + } + InstructionHandle instructionHandle4 = instructionHandle3; + value3++; + instructionHandle3 = instructionHandle4.getInstructionHandle2(); + instructionHandle2 = instructionHandle3; + } + if (value2 < 2) { + instructionHandle2 = instructionHandle; + } else { + byte value4 = 1; + InstructionHandle instructionHandle22 = instructionHandle.getInstructionHandle2(); + int value5; + int value6 = value5 = 1; + while (true) { + if (value6 >= value3) { + value = value4; + break; + } + if (!this.matchesInstructionTargeters(instructionHandle22.getTargeters())) { + value = 0; + break; + } + InstructionHandle instructionHandle5 = instructionHandle22; + value5++; + instructionHandle22 = instructionHandle5.getInstructionHandle2(); + value6 = value5; + } + if (value == 0) { + instructionHandle2 = instructionHandle; + } else { + OptimizationStatistics.count5++; + InstructionHandle instructionHandle23 = instructionHandle.getInstructionHandle2(); + int value7; + for (int value8 = value7 = 1; value8 < value3; value8 = value7) { + this.processInstructionHandle2(instructionHandle23, instructionHandle); + label68: + { + try { + instructionList.processInstructionHandle2(instructionHandle23); + } catch (TargetLostException targetLostException) { + instructionHandle2 = instructionHandle; + break label68; + } + instructionHandle2 = instructionHandle; + } + InstructionHandle instructionHandle24 = instructionHandle2.getInstructionHandle2(); + value7++; + instructionHandle23 = instructionHandle24; + } + int value9; + for (int value10 = value9 = 1; value10 < value3; value10 = ++value9) { + if (instructionHandle.getInstruction().produceStack(classGen.getConstantPool()) + == 1) { + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.DUP); + } else if (instructionHandle.getInstruction().produceStack(classGen.getConstantPool()) + == 2) { + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.DUP2); + } + } + instructionHandle2 = instructionHandle; + } + } + } + instructionHandle2 = instructionHandle = instructionHandle2.getInstructionHandle2(); + } + } + + public void processEnabled( + ClassGen classGen, MethodGen methodGen, InstructionList instructionList, boolean matches) { + int value; + InstructionHandle instructionHandle; + InstructionHandle instructionHandle2 = instructionHandle = instructionList.getStart(); + while (instructionHandle2 != null) { + if (!(instructionHandle.getInstruction() instanceof LoadInstruction)) { + instructionHandle2 = instructionHandle; + } else if (!this.matchesInstructionTargeters(instructionHandle.getTargeters())) { + instructionHandle2 = instructionHandle; + } else { + ConstantPoolGen constantPool = classGen.getConstantPool(); + int index = ((LoadInstruction) instructionHandle.getInstruction()).getIndex(); + int value2 = 0; + InstructionHandle instructionHandle3 = null; + InstructionHandle instructionHandle4 = null; + InstructionHandle instructionHandle22 = instructionHandle.getInstructionHandle2(); + int value3 = 0; + while (true) { + if (instructionHandle22 != null) { + Instruction instruction; + if (!((instruction = instructionHandle22.getInstruction()) + instanceof ArithmeticInstruction) + && !(instruction instanceof ArrayInstruction) + && !(instruction instanceof ConversionInstruction) + && !(instruction instanceof ConstantPushInstruction) + && !(instruction instanceof FieldOrMethod) + && !(instruction instanceof LocalVariableInstruction) + && !(instruction instanceof PushInstruction) + && !(instruction instanceof PopInstruction) + && !(instruction instanceof NEW) + && !(instruction instanceof NEWARRAY) + && !(instruction instanceof NOP)) { + instructionHandle2 = instructionHandle4; + break; + } + if ((instruction instanceof StoreInstruction || instruction instanceof IINC) + && ((LocalVariableInstruction) instruction).getIndex() == index) { + instructionHandle2 = instructionHandle4; + break; + } + if (!this.matchesInstructionTargeters(instructionHandle22.getTargeters())) { + instructionHandle2 = instructionHandle4; + break; + } + if (value2 == 1) { + Instruction instruction2; + if ((instruction2 = instructionHandle22.getInstruction()) instanceof LoadInstruction + && ((LoadInstruction) instruction2).getIndex() == index) { + instructionHandle3 = instructionHandle22; + } + } else { + Instruction instruction3; + if (value2 == 2 + && (instruction3 = instructionHandle22.getInstruction()) + instanceof LoadInstruction + && ((LoadInstruction) instruction3).getIndex() == index) { + instructionHandle2 = instructionHandle4 = instructionHandle22; + break; + } + } + int value4 = instructionHandle22.getInstruction().produceStack(constantPool); + int value5 = instructionHandle22.getInstruction().consumeStack(constantPool); + if (value4 != -2) { + if (value5 == -2) { + instructionHandle2 = instructionHandle4; + break; + } + int value6; + if ((value6 = value2 - value5) < 0) { + instructionHandle2 = instructionHandle4; + break; + } + value2 = value6 + value4; + instructionHandle22 = instructionHandle22.getInstructionHandle2(); + int value7 = value3++; + if (value7 <= (short) 777) { + continue; + } + instructionHandle2 = instructionHandle4; + break; + } + } + instructionHandle2 = instructionHandle4; + break; + } + InstructionHandle instructionHandle5 = + instructionHandle2 != null ? instructionHandle4 : instructionHandle3; + int value8 = instructionHandle4 != null ? 2 : 1; + if (instructionHandle5 == null) { + instructionHandle2 = instructionHandle; + } else { + label172: + { + if (!matches) { + InstructionHandle instructionHandle23 = instructionHandle.getInstructionHandle2(); + byte value9 = 0; + instructionHandle2 = instructionHandle23; + while (true) { + if (instructionHandle2 != null && instructionHandle23 != instructionHandle5) { + if (instructionHandle23.getInstruction() instanceof LoadInstruction + && ((LoadInstruction) instructionHandle23.getInstruction()).getIndex() + == index) { + instructionHandle2 = + instructionHandle23 = instructionHandle23.getInstructionHandle2(); + continue; + } + value = 1; + break; + } + value = value9; + break; + } + if (value == 0) { + instructionHandle2 = instructionHandle; + break label172; + } + } + OptimizationStatistics.count++; + InstructionHandle instructionHandle6; + InstructionHandle instructionHandle7 = + instructionHandle6 = instructionHandle.getInstructionHandle2(); + this.processInstructionHandle( + instructionHandle6.getInstructionHandle(), instructionHandle6); + this.processInstructionHandle2( + instructionHandle7.getInstructionHandle(), instructionHandle5); + label106: + { + try { + instructionList.processInstructionHandle2( + instructionHandle6.getInstructionHandle()); + } catch (TargetLostException targetLostException) { + instructionHandle2 = instructionHandle5; + break label106; + } + instructionHandle2 = instructionHandle5; + } + if (instructionHandle2.getInstruction().produceStack(constantPool) == 1) { + if (value8 == 2) { + instructionHandle2 = instructionHandle6; + instructionList.createInstructionHandle2( + instructionHandle5, InstructionConstants.DUP_X2); + } else { + instructionList.createInstructionHandle2( + instructionHandle5, InstructionConstants.DUP_X1); + instructionHandle2 = instructionHandle6; + } + } else { + label173: + { + if (instructionHandle5.getInstruction().produceStack(constantPool) == 2) { + if (value8 == 2) { + instructionHandle2 = instructionHandle6; + instructionList.createInstructionHandle2( + instructionHandle5, InstructionConstants.DUP2_X2); + break label173; + } + instructionList.createInstructionHandle2( + instructionHandle5, InstructionConstants.DUP2_X1); + } + instructionHandle2 = instructionHandle6; + } + } + } + } + } + instructionHandle2 = instructionHandle = instructionHandle2.getInstructionHandle2(); + } + } + + public void processInstructionList2( + ClassGen classGen, MethodGen methodGen, InstructionList instructionList) { + int value; + InstructionHandle instructionHandle; + InstructionHandle instructionHandle2 = instructionHandle = instructionList.getStart(); + while (instructionHandle2 != null) { + if (!(instructionHandle.getInstruction() instanceof ALOAD)) { + instructionHandle2 = instructionHandle; + } else if (instructionHandle.getInstructionHandle2() == null) { + instructionHandle2 = instructionHandle; + } else if (instructionHandle.getInstructionHandle2().getInstructionHandle2() == null) { + instructionHandle2 = instructionHandle; + } else if (instructionHandle + .getInstructionHandle2() + .getInstructionHandle2() + .getInstructionHandle2() + == null) { + instructionHandle2 = instructionHandle; + } else if (!(instructionHandle.getInstructionHandle2().getInstruction() + instanceof GETFIELD)) { + instructionHandle2 = instructionHandle; + } else if (!(instructionHandle + .getInstructionHandle2() + .getInstructionHandle2() + .getInstruction() + instanceof ALOAD)) { + instructionHandle2 = instructionHandle; + } else if (!(instructionHandle + .getInstructionHandle2() + .getInstructionHandle2() + .getInstructionHandle2() + .getInstruction() + instanceof GETFIELD)) { + instructionHandle2 = instructionHandle; + } else if (((ALOAD) instructionHandle.getInstruction()).getIndex() + != ((ALOAD) + instructionHandle + .getInstructionHandle2() + .getInstructionHandle2() + .getInstruction()) + .getIndex()) { + instructionHandle2 = instructionHandle; + } else if (instructionHandle + .getInstructionHandle2() + .getInstruction() + .produceStack(classGen.getConstantPool()) + != 1) { + instructionHandle2 = instructionHandle; + } else { + byte value2 = 1; + InstructionHandle instructionHandle22 = instructionHandle.getInstructionHandle2(); + int value3; + int value4 = value3 = 1; + while (true) { + if (value4 >= 4) { + value = value2; + break; + } + if (!this.matchesInstructionTargeters(instructionHandle22.getTargeters())) { + value = 0; + break; + } + InstructionHandle instructionHandle3 = instructionHandle22; + value3++; + instructionHandle22 = instructionHandle3.getInstructionHandle2(); + value4 = value3; + } + if (value == 0) { + instructionHandle2 = instructionHandle; + } else { + OptimizationStatistics.count11++; + instructionHandle2 = instructionHandle; + this.processInstructionHandle( + instructionHandle.getInstructionHandle2().getInstructionHandle2(), + instructionHandle + .getInstructionHandle2() + .getInstructionHandle2() + .getInstructionHandle2()); + instructionList.processInstructionHandle3( + instructionHandle.getInstructionHandle2(), + instructionHandle.getInstructionHandle2().getInstructionHandle2()); + instructionList.createInstructionHandle2( + instructionHandle.getInstructionHandle2().getInstructionHandle2(), + InstructionConstants.SWAP); + } + } + instructionHandle2 = instructionHandle = instructionHandle2.getInstructionHandle2(); + } + } + + public void processInstructionList3( + ClassGen classGen, MethodGen methodGen, InstructionList instructionList) { + byte value; + int value2; + FieldInstruction fieldInstruction; + InstructionHandle instructionHandle; + InstructionHandle instructionHandle2 = instructionHandle = instructionList.getStart(); + while (instructionHandle2 != null) { + if (!(instructionHandle.getInstruction() instanceof FieldInstruction)) { + instructionHandle2 = instructionHandle; + } else { + FieldInstruction fieldInstruction2 = (FieldInstruction) instructionHandle.getInstruction(); + if (!Configuration.getFieldRemovalOptions() + .matchesText( + "" + + fieldInstruction2.getText2(classGen.getConstantPool()) + + "." + + fieldInstruction2.getFieldName(classGen.getConstantPool()) + + fieldInstruction2.getText3(classGen.getConstantPool()))) { + instructionHandle2 = instructionHandle; + } else { + label238: + { + InstructionHandle instructionHandle3; + ConstantPoolGen constantPoolGen; + label220: + { + constantPoolGen = classGen.getConstantPool(); + int value3 = fieldInstruction2.produceStack(constantPoolGen); + instructionHandle3 = null; + if (value3 > 0) { + if (instructionHandle.getInstructionHandle2() != null + && (instructionHandle.getInstructionHandle2().getInstruction() instanceof POP + || instructionHandle.getInstructionHandle2().getInstruction() + instanceof POP2) + && instructionHandle + .getInstructionHandle2() + .getInstruction() + .consumeStack(constantPoolGen) + == value3) { + instructionHandle3 = instructionHandle.getInstructionHandle2(); + } + if (instructionHandle3 == null) { + instructionHandle3 = instructionHandle; + if (Type.INT.equals(fieldInstruction2.getType2(constantPoolGen)) + || Type.SHORT.equals(fieldInstruction2.getType2(constantPoolGen)) + || Type.BYTE.equals(fieldInstruction2.getType2(constantPoolGen)) + || Type.BOOLEAN.equals(fieldInstruction2.getType2(constantPoolGen)) + || Type.CHAR.equals(fieldInstruction2.getType2(constantPoolGen))) { + instructionList.createInstructionHandle2(instructionHandle3, new ICONST(0)); + } else if (Type.LONG.equals(fieldInstruction2.getType2(constantPoolGen))) { + instructionList.createInstructionHandle2(instructionHandle3, new LCONST(0L)); + } else if (Type.FLOAT.equals(fieldInstruction2.getType2(constantPoolGen))) { + instructionList.createInstructionHandle2(instructionHandle3, new FCONST(0.0F)); + } else if (Type.DOUBLE.equals(fieldInstruction2.getType2(constantPoolGen))) { + instructionList.createInstructionHandle2(instructionHandle3, new DCONST(0.0)); + } else if (fieldInstruction2.getType2(constantPoolGen) instanceof ArrayType) { + instructionList.createInstructionHandle2(instructionHandle3, new ACONST_NULL()); + } else { + if (!(fieldInstruction2.getType2(constantPoolGen) instanceof ObjectType)) { + Log.warn( + "[remove-fields] Cannot remove field usage (" + + fieldInstruction2.getText2(constantPoolGen) + + "." + + fieldInstruction2.getFieldName(constantPoolGen) + + ") in " + + classGen.getClassName() + + "." + + methodGen.getName() + + " - the value is used"); + instructionHandle2 = instructionHandle; + break label238; + } + instructionList.createInstructionHandle2(instructionHandle3, new ACONST_NULL()); + } + Log.warn( + "[remove-fields] the value of " + + fieldInstruction2.getText2(constantPoolGen) + + "." + + fieldInstruction2.getFieldName(constantPoolGen) + + " in " + + classGen.getClassName() + + "." + + methodGen.getName() + + " was replaced with null(0)"); + fieldInstruction = fieldInstruction2; + break label220; + } + } else { + instructionHandle3 = instructionHandle; + } + fieldInstruction = fieldInstruction2; + } + int value4 = fieldInstruction.consumeStack(constantPoolGen); + InstructionHandle instructionHandle4; + instructionHandle2 = instructionHandle4 = instructionHandle; + while (true) { + if (instructionHandle2.getInstructionHandle() == null) { + value2 = value4; + break; + } + if (value4 == 0) { + value2 = value4; + break; + } + instructionHandle4 = instructionHandle4.getInstructionHandle(); + value4 -= + instructionHandle4.getInstruction().produceStack(constantPoolGen) + - instructionHandle4.getInstruction().consumeStack(constantPoolGen); + instructionHandle2 = instructionHandle4; + } + if (value2 != 0) { + Log.warn( + "[remove-fields] Cannot remove field usage (" + + fieldInstruction2.getText2(constantPoolGen) + + "." + + fieldInstruction2.getFieldName(constantPoolGen) + + ") in " + + classGen.getClassName() + + "." + + methodGen.getName() + + " - object not found"); + instructionHandle2 = instructionHandle; + } else { + InstructionHandle instructionHandle5 = instructionHandle4; + InstructionHandle instructionHandle6 = instructionHandle4; + int value5 = 0; + label191: + while (true) { + instructionHandle2 = instructionHandle6; + while (instructionHandle2 != instructionHandle3 + && instructionHandle6.getInstructionHandle2() != null) { + instructionHandle6 = instructionHandle6.getInstructionHandle2(); + if (this.matchesInstructionTargeters(instructionHandle6.getTargeters())) { + continue label191; + } + InstructionHandle instructionHandle7 = instructionHandle6; + value5++; + instructionHandle2 = instructionHandle7; + } + if (value5 == 1) { + byte value6 = 0; + InstructionTargeter[] instructionTargeters; + if ((instructionTargeters = instructionHandle3.getTargeters()) != null) { + InstructionTargeter[] instructionTargeters2 = instructionTargeters; + int value7 = instructionTargeters.length; + int value8; + for (int value9 = value8 = 0; value9 < value7; value9 = ++value8) { + InstructionTargeter instructionTargeter; + if (!((instructionTargeter = instructionTargeters2[value8]) + instanceof LineNumberGen) + && !(instructionTargeter instanceof LocalVariableGen) + && instructionTargeter instanceof CodeExceptionGen) { + value6 = 1; + } + } + } + if (value6 != 0 && instructionHandle5 != instructionHandle3) { + instructionHandle3.setInstruction(InstructionConstants.NOP); + instructionHandle3 = instructionHandle3.getInstructionHandle(); + value5 = 0; + } + } + if (value5 > 0) { + Log.warn( + "[remove-fields] Cannot remove field usage (" + + fieldInstruction2.getText2(constantPoolGen) + + "." + + fieldInstruction2.getFieldName(constantPoolGen) + + ") in " + + classGen.getClassName() + + "." + + methodGen.getName() + + " - targeters inside block"); + instructionHandle2 = instructionHandle; + } else { + InstructionHandle instructionHandle8; + if ((instructionHandle8 = instructionHandle3.getInstructionHandle2()) == null) { + Log.warn( + "[remove-fields] Cannot remove field usage (" + + fieldInstruction2.getText2(constantPoolGen) + + "." + + fieldInstruction2.getFieldName(constantPoolGen) + + ") in " + + classGen.getClassName() + + "." + + methodGen.getName() + + " - unexpected end of block"); + instructionHandle2 = instructionHandle; + } else { + InstructionTargeter[] instructionTargeters3; + if ((instructionTargeters3 = instructionHandle5.getTargeters()) != null) { + InstructionTargeter[] instructionTargeters4 = instructionTargeters3; + int value10 = instructionTargeters3.length; + int value11; + for (int value12 = value11 = 0; value12 < value10; value12 = ++value11) { + InstructionTargeter instructionTargeter2; + if (!((instructionTargeter2 = instructionTargeters4[value11]) + instanceof LineNumberGen) + && !(instructionTargeter2 instanceof LocalVariableGen)) { + instructionTargeter2.updateTarget(instructionHandle5, instructionHandle8); + } + } + } + InstructionHandle instructionHandle9 = instructionHandle8; + do { + instructionHandle9 = instructionHandle9.getInstructionHandle(); + this.processInstructionHandle(instructionHandle9, instructionHandle8); + this.processInstructionHandle2(instructionHandle9, instructionHandle8); + } while (instructionHandle9 != instructionHandle5 + && instructionHandle9.getInstructionHandle() != null); + byte value13 = 0; + InstructionHandle instructionHandle10; + instructionHandle2 = instructionHandle10 = instructionHandle3; + while (true) { + if (instructionHandle2 == instructionHandle5) { + value = value13; + break; + } + if (instructionHandle10.getInstruction() instanceof IfInstruction) { + byte value14 = 1; + instructionHandle5 = instructionHandle10.getInstructionHandle2(); + value = value14; + break; + } + instructionHandle2 = + instructionHandle10 = instructionHandle10.getInstructionHandle(); + } + label145: + if (value == 0) { + try { + instructionList.processInstructionHandle( + instructionHandle5, instructionHandle3); + } catch (TargetLostException targetLostException) { + instructionHandle2 = instructionHandle8; + break label145; + } + instructionHandle2 = instructionHandle8; + } else { + label236: + { + int value15 = + instructionHandle3.getInstruction().consumeStack(constantPoolGen); + InstructionHandle instructionHandle11; + for (InstructionHandle instructionHandle12 = + instructionHandle11 = instructionHandle5; + instructionHandle12 != instructionHandle3; + instructionHandle12 = + instructionHandle11 = instructionHandle11.getInstructionHandle2()) { + value15 -= + instructionHandle11.getInstruction().produceStack(constantPoolGen) + - instructionHandle11 + .getInstruction() + .consumeStack(constantPoolGen); + } + int value16; + for (int value17 = value16 = 0; value17 < value15; value17 = value16) { + value16++; + instructionList.createInstructionHandle2(instructionHandle3, new POP()); + } + try { + instructionList.processInstructionHandle( + instructionHandle5, instructionHandle3); + } catch (TargetLostException targetLostException2) { + instructionHandle2 = instructionHandle8; + break label236; + } + instructionHandle2 = instructionHandle8; + } + } + if (instructionHandle2.getInstructionHandle() != null) { + instructionHandle2 = instructionHandle8.getInstructionHandle(); + } else { + InstructionHandle instructionHandle13 = instructionHandle8; + instructionHandle2 = instructionHandle13; + } + } + } + break; + } + } + } + } + } + instructionHandle2 = instructionHandle = instructionHandle2.getInstructionHandle2(); + } + } + + public void processInstructionList4( + ClassGen classGen, MethodGen methodGen, InstructionList instructionList) { + InstructionHandle instructionHandle; + int value; + for (InstructionHandle instructionHandle2 = instructionHandle = instructionList.getStart(); + instructionHandle2 != null; + instructionHandle2 = instructionHandle = instructionHandle.getInstructionHandle2()) { + for (int value2 = value = 0; value2 < 1 + RandomUtils.calculateCount(3); value2 = value) { + instructionList.createInstructionHandle( + instructionHandle, new BIPUSH((byte) (RandomUtils.calculateCount(120) - 120))); + value++; + instructionList.createInstructionHandle(instructionHandle, InstructionConstants.POP); + } + } + } + + public void processInstructionList5( + ClassGen classGen, MethodGen methodGen, InstructionList instructionList) { + LocalVariableGen[] localVariableGens; + if ((localVariableGens = methodGen.getLocalVariables()) != null) { + if (localVariableGens.length != 0) { + boolean[] matchess = new boolean[methodGen.getCount()]; + int value = methodGen.getArgumentNames().length; + if (!methodGen.isEnabled11()) { + value++; + } + Type[] types; + int value2 = (types = methodGen.getArgumentTypes()).length; + int value3; + for (int value4 = value3 = 0; value4 < value2; value4 = ++value3) { + Type type; + if ((type = types[value3]) == Type.LONG || type == Type.DOUBLE) { + value++; + } + } + InstructionHandle instructionHandle; + InstructionHandle instructionHandle2 = instructionHandle = instructionList.getStart(); + while (instructionHandle2 != null) { + if (instructionHandle.getInstruction() instanceof LoadInstruction) { + LoadInstruction loadInstruction = (LoadInstruction) instructionHandle.getInstruction(); + instructionHandle2 = instructionHandle; + matchess[loadInstruction.getIndex()] = true; + } else { + if (instructionHandle.getInstruction() instanceof RET) { + RET rET = (RET) instructionHandle.getInstruction(); + matchess[rET.getIndex()] = true; + } + instructionHandle2 = instructionHandle; + } + instructionHandle2 = instructionHandle = instructionHandle2.getInstructionHandle2(); + } + InstructionHandle instructionHandle3; + instructionHandle2 = instructionHandle3 = instructionList.getStart(); + while (instructionHandle2 != null) { + if (instructionHandle3.getInstruction() instanceof StoreInstruction) { + StoreInstruction storeInstruction = + (StoreInstruction) instructionHandle3.getInstruction(); + if (!matchess[storeInstruction.getIndex()] && storeInstruction.getIndex() >= value) { + if (storeInstruction instanceof ASTORE + || storeInstruction instanceof ISTORE + || storeInstruction instanceof FSTORE) { + instructionHandle3.setInstruction(InstructionConstants.POP); + } else if (storeInstruction instanceof LSTORE || storeInstruction instanceof DSTORE) { + instructionHandle3.setInstruction(InstructionConstants.POP2); + } + } + } else if (instructionHandle3.getInstruction() instanceof IINC) { + IINC iNC = (IINC) instructionHandle3.getInstruction(); + if (!matchess[iNC.getIndex()] && iNC.getIndex() >= value) { + InstructionHandle instructionHandle4 = instructionHandle3; + instructionHandle3 = instructionHandle3.getInstructionHandle2(); + if (this.matchesInstructionTargeters(instructionHandle4.getTargeters())) { + try { + instructionList.processInstructionHandle2(instructionHandle4); + } catch (TargetLostException targetLostException) { + instructionHandle2 = instructionHandle3; + continue; + } + instructionHandle2 = instructionHandle3; + continue; + } + instructionHandle4.setInstruction(InstructionConstants.NOP); + instructionHandle2 = instructionHandle3; + continue; + } + } + instructionHandle2 = instructionHandle3 = instructionHandle3.getInstructionHandle2(); + } + LocalVariableGen[] localVariableGens2 = localVariableGens; + int value5 = localVariableGens.length; + int value6; + for (int value7 = value6 = 0; value7 < value5; value7 = ++value6) { + LocalVariableGen localVariableGen; + if ((localVariableGen = localVariableGens2[value6]).getIndex() >= value + && !matchess[localVariableGen.getIndex()]) { + methodGen.removeLocalVariable(localVariableGen); + OptimizationStatistics.count16++; + } + } + } + } + } + + public boolean matchesInstructionHandle( + InstructionList instructionList, + InstructionHandle instructionHandle, + InstructionHandle instructionHandle2) { + int index = ((LocalVariableInstruction) instructionHandle.getInstruction()).getIndex(); + InstructionHandle instructionHandle3; + for (InstructionHandle instructionHandle4 = instructionHandle3 = instructionList.getStart(); + instructionHandle4 != null; + instructionHandle4 = instructionHandle3 = instructionHandle3.getInstructionHandle2()) { + Instruction instruction; + if ((instruction = instructionHandle3.getInstruction()) instanceof LocalVariableInstruction + && ((LocalVariableInstruction) instruction).getIndex() == index + && instructionHandle3 != instructionHandle + && instructionHandle3 != instructionHandle2) { + return false; + } + } + return true; + } + + public void processInstructionList6( + ClassGen classGen, MethodGen methodGen, InstructionList instructionList) { + int value; + int value2; + InstructionHandle instructionHandle; + InstructionHandle instructionHandle2 = instructionHandle = instructionList.getStart(); + while (instructionHandle2 != null) { + if (!(instructionHandle.getInstruction() instanceof IINC)) { + instructionHandle2 = instructionHandle; + } else if (!this.matchesInstructionTargeters(instructionHandle.getTargeters())) { + instructionHandle2 = instructionHandle; + } else { + IINC iNC = (IINC) instructionHandle.getInstruction(); + int value3 = 0; + byte value4 = 0; + InstructionHandle instructionHandle3 = instructionHandle.getInstructionHandle(); + label141: + while (true) { + instructionHandle2 = instructionHandle3; + while (instructionHandle2 != null && value3 < 3) { + if (!this.matchesInstructionTargeters(instructionHandle3.getTargeters())) { + value2 = value4; + break label141; + } + if (instructionHandle3.getInstruction() instanceof BranchInstruction) { + value2 = value4; + break label141; + } + if (instructionHandle3.getInstruction() instanceof LocalVariableInstruction + && ((LocalVariableInstruction) instructionHandle3.getInstruction()).getIndex() + == iNC.getIndex()) { + value2 = value4; + break label141; + } + if (instructionHandle3.getInstruction() instanceof ArrayInstruction) { + value2 = 1; + break label141; + } + if ((instructionHandle3 = instructionHandle3.getInstructionHandle()) == null) { + continue label141; + } + InstructionHandle instructionHandle4 = instructionHandle3; + value3++; + instructionHandle2 = instructionHandle4; + } + value2 = value4; + break; + } + if (value2 != 0) { + InstructionHandle instructionHandle22 = instructionHandle.getInstructionHandle2(); + instructionHandle2 = instructionHandle22; + this.processInstructionHandle( + instructionHandle22.getInstructionHandle(), instructionHandle22); + instructionList.processInstructionHandle3( + instructionHandle22.getInstructionHandle(), + instructionHandle3.getInstructionHandle()); + OptimizationStatistics.count27++; + OptimizationStatistics.count20++; + } else { + label155: + { + int value5 = 0; + if (value3 < 3) { + byte value6 = 0; + InstructionHandle instructionHandle23 = instructionHandle.getInstructionHandle2(); + label115: + while (true) { + instructionHandle2 = instructionHandle23; + while (instructionHandle2 != null && value5 < 3) { + if (!this.matchesInstructionTargeters(instructionHandle23.getTargeters())) { + value = value6; + break label115; + } + if (instructionHandle23.getInstruction() instanceof BranchInstruction) { + value = value6; + break label115; + } + if (instructionHandle23.getInstruction() instanceof LocalVariableInstruction + && ((LocalVariableInstruction) instructionHandle23.getInstruction()) + .getIndex() + == iNC.getIndex()) { + value = value6; + break label115; + } + if (value5 > 0 + && instructionHandle23.getInstruction() instanceof ArrayInstruction) { + value = 1; + break label115; + } + if ((instructionHandle23 = instructionHandle23.getInstructionHandle2()) == null) { + continue label115; + } + InstructionHandle instructionHandle5 = instructionHandle23; + value5++; + instructionHandle2 = instructionHandle5; + } + value = value6; + break; + } + if (value != 0) { + this.processInstructionHandle( + instructionHandle, instructionHandle.getInstructionHandle2()); + instructionList.processInstructionHandle3( + instructionHandle, instructionHandle23.getInstructionHandle()); + InstructionHandle instructionHandle6 = instructionHandle23; + OptimizationStatistics.count27++; + OptimizationStatistics.count20++; + instructionHandle2 = instructionHandle6; + break label155; + } + } + if (value3 == 0 && value5 == 0) { + instructionHandle2 = instructionHandle; + } else { + OptimizationStatistics.count27++; + this.processInstructionHandle( + instructionHandle, instructionHandle.getInstructionHandle2()); + if (value3 > 3) { + value3 = 3; + } + if (value5 > 3) { + value5 = 3; + } + if (value3 == 3) { + InstructionHandle instructionHandle24 = instructionHandle.getInstructionHandle2(); + InstructionHandle instructionHandle7 = instructionHandle24.getInstructionHandle(); + instructionHandle2 = instructionHandle24; + instructionList.processInstructionHandle3( + instructionHandle7, + instructionHandle24 + .getInstructionHandle() + .getInstructionHandle() + .getInstructionHandle() + .getInstructionHandle() + .getInstructionHandle()); + } else if (value5 == 3) { + instructionHandle2 = instructionHandle; + instructionList.processInstructionHandle3( + instructionHandle, + instructionHandle + .getInstructionHandle2() + .getInstructionHandle2() + .getInstructionHandle2()); + } else if (value3 == 2) { + InstructionHandle instructionHandle25 = instructionHandle.getInstructionHandle2(); + InstructionHandle instructionHandle8 = instructionHandle25.getInstructionHandle(); + instructionHandle2 = instructionHandle25; + instructionList.processInstructionHandle3( + instructionHandle8, + instructionHandle25 + .getInstructionHandle() + .getInstructionHandle() + .getInstructionHandle() + .getInstructionHandle()); + } else if (value5 == 2) { + instructionHandle2 = instructionHandle; + instructionList.processInstructionHandle3( + instructionHandle, + instructionHandle.getInstructionHandle2().getInstructionHandle2()); + } else if (value3 == 1) { + InstructionHandle instructionHandle26 = instructionHandle.getInstructionHandle2(); + InstructionHandle instructionHandle9 = instructionHandle26.getInstructionHandle(); + instructionHandle2 = instructionHandle26; + instructionList.processInstructionHandle3( + instructionHandle9, + instructionHandle26 + .getInstructionHandle() + .getInstructionHandle() + .getInstructionHandle()); + } else { + if (value5 == 1) { + instructionList.processInstructionHandle3( + instructionHandle, instructionHandle.getInstructionHandle2()); + } + instructionHandle2 = instructionHandle; + } + } + } + } + } + instructionHandle2 = instructionHandle = instructionHandle2.getInstructionHandle2(); + } + } + + public void processInstructionList7( + ClassGen classGen, MethodGen methodGen, InstructionList instructionList) { + if (classGen.getMajor() <= 50) { + InstructionHandle instructionHandle = null; + InstructionHandle instructionHandle2 = null; + InstructionHandle instructionHandle3; + InstructionHandle instructionHandle4 = instructionHandle3 = instructionList.getStart(); + while (true) { + if (instructionHandle4 == null) { + instructionHandle4 = instructionHandle; + break; + } + if (!(instructionHandle3.getInstruction() instanceof GOTO) + && !(instructionHandle3.getInstruction() instanceof ReturnInstruction)) { + instructionHandle4 = instructionHandle2; + } else if (instructionHandle3.getInstructionHandle2() == null) { + instructionHandle4 = instructionHandle2; + } else { + label46: + { + if (instructionHandle3.getInstruction() instanceof GOTO) { + GOTO gOTO; + if ((gOTO = (GOTO) instructionHandle3.getInstruction()).getTarget() == null) { + instructionHandle4 = instructionHandle2; + break label46; + } + if (Math.abs(instructionHandle3.getPosition() - gOTO.getTarget().getPosition()) + > 32000) { + instructionHandle4 = instructionHandle2; + break label46; + } + } + if (instructionHandle == null) { + instructionHandle = instructionHandle3; + instructionHandle4 = instructionHandle2; + } else { + instructionHandle2 = instructionHandle3; + instructionHandle4 = instructionHandle2; + } + } + } + if (instructionHandle4 != null) { + instructionHandle4 = instructionHandle; + break; + } + instructionHandle4 = instructionHandle3 = instructionHandle3.getInstructionHandle2(); + } + if (instructionHandle4 != null) { + instructionList.createInstructionHandle2(instructionHandle, InstructionConstants.POP); + OptimizationStatistics.count32++; + if (instructionHandle2 != null) { + instructionList.createInstructionHandle2( + instructionHandle2, InstructionConstants.ICONST_0); + } + } + } + } + + public void processEnabled2( + ClassGen classGen, MethodGen methodGen, InstructionList instructionList, boolean matches) { + Vector vector; + InstructionHandle instructionHandle; + InstructionHandle instructionHandle2 = instructionHandle = instructionList.getStart(); + while (instructionHandle2 != null) { + if (!(instructionHandle.getInstruction() instanceof ALOAD)) { + instructionHandle2 = instructionHandle; + } else { + int index = ((ALOAD) instructionHandle.getInstruction()).getIndex(); + if (!matches && !this.matchesInstructionTargeters(instructionHandle.getTargeters())) { + instructionHandle2 = instructionHandle; + } else { + ConstantPoolGen constantPool = classGen.getConstantPool(); + int value = instructionHandle.getInstruction().produceStack(constantPool); + Vector vector2; + (vector2 = new Vector()).add(instructionHandle); + InstructionHandle instructionHandle22 = instructionHandle.getInstructionHandle2(); + int value2 = 0; + while (true) { + if (instructionHandle22 != null) { + Instruction instruction; + if (!((instruction = instructionHandle22.getInstruction()) + instanceof ArithmeticInstruction) + && !(instruction instanceof ArrayInstruction) + && !(instruction instanceof ConversionInstruction) + && !(instruction instanceof ConstantPushInstruction) + && !(instruction instanceof FieldOrMethod) + && !(instruction instanceof LocalVariableInstruction) + && !(instruction instanceof PushInstruction) + && !(instruction instanceof PopInstruction) + && !(instruction instanceof NEW) + && !(instruction instanceof NEWARRAY) + && !(instruction instanceof NOP)) { + vector = vector2; + break; + } + if (!this.matchesInstructionTargeters(instructionHandle22.getTargeters())) { + vector = vector2; + break; + } + label121: + { + if (value == 0 && instructionHandle22.getInstruction() instanceof ALOAD) { + if (!matches) { + instructionHandle2 = instructionHandle22; + vector2.add(instructionHandle22); + break label121; + } + if (((ALOAD) instructionHandle22.getInstruction()).getIndex() == index) { + vector2.add(instructionHandle22); + } + } + instructionHandle2 = instructionHandle22; + } + if (instructionHandle2.getInstruction() instanceof ASTORE) { + if (matches + && ((ASTORE) instructionHandle22.getInstruction()).getIndex() == index) { + vector = vector2; + break; + } + if (!matches) { + vector = vector2; + break; + } + } + int value3 = instructionHandle22.getInstruction().produceStack(constantPool); + int value4 = instructionHandle22.getInstruction().consumeStack(constantPool); + if (value3 != -2) { + if (value4 == -2) { + vector = vector2; + break; + } + int value5; + if ((value5 = value - value4) < 0) { + vector = vector2; + break; + } + value = value5 + value3; + instructionHandle22 = instructionHandle22.getInstructionHandle2(); + int value6 = value2++; + if (value6 <= (short) 777) { + continue; + } + vector = vector2; + break; + } + } + vector = vector2; + break; + } + if (vector.size() < 2) { + instructionHandle2 = instructionHandle; + } else { + if (vector2.size() > 1) { + OptimizationStatistics.count14++; + } + if (vector2.size() > 2) { + OptimizationStatistics.count33++; + } + int value7; + int value8; + if (matches) { + for (int value9 = value8 = vector2.size() - 1; value9 >= 1; value9 = value8) { + this.processInstructionHandle( + (InstructionHandle) vector2.get(value8), + ((InstructionHandle) vector2.get(value8)).getInstructionHandle2()); + InstructionHandle instructionHandle3 = (InstructionHandle) vector2.get(value8); + Vector vector3 = vector2; + value8--; + instructionList.processInstructionHandle3( + instructionHandle3, (InstructionHandle) vector3.get((byte) 0)); + } + } else { + for (int value10 = value7 = vector2.size() - 1; value10 >= 1; value10 = value7) { + this.processInstructionHandle( + (InstructionHandle) vector2.get(value7), + ((InstructionHandle) vector2.get(value7)).getInstructionHandle2()); + InstructionHandle instructionHandle4 = (InstructionHandle) vector2.get(value7); + Object result = vector2.get(0); + value7--; + instructionList.processInstructionHandle3( + instructionHandle4, ((InstructionHandle) result).getInstructionHandle()); + } + } + instructionHandle2 = instructionHandle; + } + } + } + instructionHandle2 = instructionHandle = instructionHandle2.getInstructionHandle2(); + } + } + + public void processInstructionList8( + ClassGen classGen, MethodGen methodGen, InstructionList instructionList) { + OptimizationStatistics.count30++; + LocalVariableGen[] localVariableGens; + if ((localVariableGens = methodGen.getLocalVariables()) != null) { + if (localVariableGens.length != 0) { + boolean[] matchess = new boolean[methodGen.getCount()]; + int value = methodGen.getArgumentNames().length; + if (!methodGen.isEnabled11()) { + value++; + } + Type[] types; + int value2 = (types = methodGen.getArgumentTypes()).length; + int value3; + for (int value4 = value3 = 0; value4 < value2; value4 = ++value3) { + Type type; + if ((type = types[value3]) == Type.LONG || type == Type.DOUBLE) { + value++; + } + } + LocalVariableGen[] localVariableGens2 = localVariableGens; + int value5 = localVariableGens.length; + int value6; + for (int value7 = value6 = 0; value7 < value5; value7 = ++value6) { + LocalVariableGen localVariableGen; + if ((localVariableGen = localVariableGens2[value6]).getType() == Type.BOOLEAN + || localVariableGen.getType() == Type.BYTE + || localVariableGen.getType() == Type.SHORT + || localVariableGen.getType() == Type.CHAR) { + localVariableGen.setType(Type.INT); + } + } + InstructionHandle instructionHandle; + for (InstructionHandle instructionHandle2 = instructionHandle = instructionList.getStart(); + instructionHandle2 != null; + instructionHandle2 = instructionHandle = instructionHandle.getInstructionHandle2()) { + if (instructionHandle.getInstruction() instanceof LocalVariableInstruction) { + LocalVariableInstruction localVariableInstruction = + (LocalVariableInstruction) instructionHandle.getInstruction(); + matchess[localVariableInstruction.getIndex()] = true; + } + } + LocalVariableGen[] localVariableGens3 = localVariableGens; + int value8 = localVariableGens.length; + int value9; + for (int value10 = value9 = 0; value10 < value8; value10 = ++value9) { + LocalVariableGen localVariableGen2; + if ((localVariableGen2 = localVariableGens3[value9]).getIndex() >= value + && !matchess[localVariableGen2.getIndex()]) { + methodGen.removeLocalVariable(localVariableGen2); + OptimizationStatistics.count6++; + } + } + instructionList.update(); + LocalVariableGen[] localVariableGens4 = localVariableGens; + int value11 = localVariableGens.length; + int value12; + for (int value13 = value12 = 0; value13 < value11; value13 = ++value12) { + LocalVariableGen localVariableGen3; + if ((localVariableGen3 = localVariableGens4[value12]).getInstructionHandle() != null + && localVariableGen3.getInstructionHandle2() != null + && localVariableGen3.getInstructionHandle().getPosition() + > localVariableGen3.getInstructionHandle2().getPosition()) { + InstructionHandle instructionHandle3 = localVariableGen3.getInstructionHandle(); + localVariableGen3.processInstructionHandle2(localVariableGen3.getInstructionHandle2()); + localVariableGen3.processInstructionHandle(instructionHandle3); + } + } + } + } + } + + public void processCount( + ClassGen classGen, MethodGen methodGen, InstructionList instructionList, int value) { + InstructionList instructionList2; + InstructionList instructionList3; + InstructionList instructionList4; + int value2 = 0; + InstructionHandle instructionHandle; + InstructionHandle instructionHandle2 = instructionHandle = instructionList.getStart(); + while (instructionHandle2 != null) { + if (value2 >= value) { + instructionHandle2 = instructionHandle; + } else if (!this.matchesInstructionTargeters(instructionHandle.getTargeters())) { + instructionHandle2 = instructionHandle; + } else { + if (instructionHandle.getInstruction() instanceof ConstantPushInstruction) { + ConstantPoolGen constantPool = classGen.getConstantPool(); + ConstantPushInstruction constantPushInstruction; + if ((constantPushInstruction = + (ConstantPushInstruction) instructionHandle.getInstruction()) + .getType(constantPool) + == Type.LONG + && constantPushInstruction instanceof LCONST) { + LCONST lCONST; + if ((lCONST = (LCONST) constantPushInstruction).getValue().longValue() == 0L) { + InstructionHandle instructionHandle3 = + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.I2L); + InstructionHandle instructionHandle4 = + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.ICONST_0); + this.processInstructionHandle(instructionHandle, instructionHandle4); + label113: + { + label94: + { + try { + this.processInstructionHandle2(instructionHandle, instructionHandle3); + } catch (ClassGenException classGenException) { + { + instructionList4 = instructionList; + break label94; + } + } + instructionList4 = instructionList; + } + try { + instructionList4.processInstructionHandle2(instructionHandle); + } catch (TargetLostException targetLostException) { + instructionHandle2 = instructionHandle3; + break label113; + } + instructionHandle2 = instructionHandle3; + } + instructionHandle = instructionHandle2; + value2++; + } else if (lCONST.getValue().longValue() == 1L) { + InstructionHandle instructionHandle5 = + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.I2L); + InstructionHandle instructionHandle6 = + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.ICONST_1); + this.processInstructionHandle(instructionHandle, instructionHandle6); + label115: + { + label82: + { + try { + this.processInstructionHandle2(instructionHandle, instructionHandle5); + } catch (ClassGenException classGenException2) { + { + instructionList3 = instructionList; + break label82; + } + } + instructionList3 = instructionList; + } + try { + instructionList3.processInstructionHandle2(instructionHandle); + } catch (TargetLostException targetLostException2) { + instructionHandle2 = instructionHandle5; + break label115; + } + instructionHandle2 = instructionHandle5; + } + instructionHandle = instructionHandle2; + value2++; + } + } + } else if (instructionHandle.getInstruction() instanceof LDC2_W) { + LDC2_W lDC2_W = (LDC2_W) instructionHandle.getInstruction(); + ConstantPoolGen constantPool2 = classGen.getConstantPool(); + if (lDC2_W.getType(constantPool2) == Type.LONG) { + long value3; + long value4 = value3 = lDC2_W.getValue(constantPool2).longValue(); + if (value4 == (short) value4) { + InstructionHandle instructionHandle7 = + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.I2L); + InstructionHandle instructionHandle22 = + instructionList.getInstructionHandle2( + instructionHandle, new PUSH(classGen.getConstantPool(), (short) value3)); + this.processInstructionHandle(instructionHandle, instructionHandle22); + label117: + { + label68: + { + try { + this.processInstructionHandle2(instructionHandle, instructionHandle7); + } catch (ClassGenException classGenException3) { + { + instructionList2 = instructionList; + break label68; + } + } + instructionList2 = instructionList; + } + try { + instructionList2.processInstructionHandle2(instructionHandle); + } catch (TargetLostException targetLostException3) { + instructionHandle2 = instructionHandle7; + break label117; + } + instructionHandle2 = instructionHandle7; + } + instructionHandle = instructionHandle2; + value2++; + } + } + } + instructionHandle2 = instructionHandle; + } + instructionHandle2 = instructionHandle = instructionHandle2.getInstructionHandle2(); + } + } + + public static int[] getCounts(int value) { + int value2 = 0; + int value3 = 0; + int value4; + for (int value5 = value4 = 0; value5 < 32; value5 = ++value4) { + if ((value >> value4) % 2 == 1) { + if (RandomUtils.calculateValue() < 0.5) { + value2 |= 1 << value4; + } else { + value3 |= 1 << value4; + } + } + } + return new int[] {value2, value3}; + } + + public void processInstructionList9( + ClassGen classGen, MethodGen methodGen, InstructionList instructionList) { + IfInstruction ifInstruction; + int value; + instructionList.update(); + InstructionHandle instructionHandle = null; + InstructionHandle instructionHandle2; + InstructionHandle instructionHandle3 = instructionHandle2 = instructionList.getStart(); + while (instructionHandle3 != null) { + if (instructionHandle2.getInstruction() instanceof IfInstruction) { + instructionHandle = instructionHandle2; + } + if (!(instructionHandle2.getInstruction() instanceof GOTO)) { + instructionHandle3 = instructionHandle2; + } else { + label176: + { + InstructionHandle instructionHandle4 = instructionHandle2; + GOTO gOTO = (GOTO) instructionHandle2.getInstruction(); + if (instructionHandle4.getInstructionHandle2() != null) { + if (gOTO.getTarget() == null) { + instructionHandle3 = instructionHandle2; + break label176; + } + if (instructionHandle4.getInstructionHandle2() == gOTO.getTarget()) { + instructionHandle3 = instructionHandle2; + break label176; + } + if (instructionHandle4.getInstructionHandle2().getInstructionHandle2() + == gOTO.getTarget()) { + instructionHandle3 = instructionHandle2; + break label176; + } + if (instructionHandle4.getPosition() > gOTO.getTarget().getPosition()) { + instructionHandle3 = instructionHandle2; + break label176; + } + IfInstruction ifInstruction2 = null; + InstructionHandle instructionHandle5; + if ((instructionHandle5 = instructionHandle4.getInstructionHandle2()).getTargeters() + == null) { + instructionHandle3 = instructionHandle2; + break label176; + } + InstructionTargeter[] instructionTargeters; + int value2 = (instructionTargeters = instructionHandle5.getTargeters()).length; + int value3; + for (int value4 = value3 = 0; value4 < value2; value4 = ++value3) { + InstructionTargeter instructionTargeter; + if ((instructionTargeter = instructionTargeters[value3]) instanceof IfInstruction) { + ifInstruction2 = (IfInstruction) instructionTargeter; + } + } + if (instructionHandle == null) { + instructionHandle3 = instructionHandle2; + break label176; + } + if (instructionHandle.getInstruction() != ifInstruction2) { + instructionHandle3 = instructionHandle2; + break label176; + } + if (instructionHandle.getInstructionHandle2() != null) { + if (instructionHandle.getInstructionHandle2().getInstructionHandle2() == null) { + instructionHandle3 = instructionHandle2; + break label176; + } + label150: + if (instructionHandle.getInstructionHandle2() != instructionHandle4) { + if (instructionHandle.getInstructionHandle2().getInstructionHandle2() + == instructionHandle4) { + instructionHandle3 = instructionHandle2; + break label176; + } + InstructionHandle instructionHandle6 = instructionHandle; + byte value5 = 1; + instructionHandle3 = instructionHandle6; + while (true) { + if (instructionHandle3 != null) { + if (instructionHandle6 != instructionHandle5) { + if (!this.matchesInstructionTargeters(instructionHandle6.getTargeters())) { + value = 0; + break; + } + instructionHandle3 = + instructionHandle6 = instructionHandle6.getInstructionHandle2(); + continue; + } + InstructionTargeter[] instructionTargeters2; + int value6 = (instructionTargeters2 = instructionHandle5.getTargeters()).length; + int value7; + for (int value8 = value7 = 0; value8 < value6; value8 = ++value7) { + InstructionTargeter instructionTargeter2; + if (!((instructionTargeter2 = instructionTargeters2[value7]) + instanceof LineNumberGen) + && !(instructionTargeter2 instanceof LocalVariableGen) + && instructionTargeter2 != ifInstruction2) { + value5 = 0; + break; + } + } + } + value = value5; + break; + } + if (value == 0) { + instructionHandle3 = instructionHandle2; + break label176; + } + Instruction instruction; + if ((!((instruction = instructionHandle5.getInstruction()) + instanceof LoadInstruction) + || !instruction.equals( + instructionHandle.getInstructionHandle2().getInstruction())) + && (!this.matchesInstruction(instruction) + || !this.matchesConstantPoolGen( + instruction, + instructionHandle.getInstructionHandle2().getInstruction(), + classGen.getConstantPool()))) { + if (!(instruction instanceof NEW)) { + break label150; + } + if (!instruction.equals( + instructionHandle.getInstructionHandle2().getInstruction())) { + instructionHandle3 = instructionHandle2; + break label176; + } + } + if (instruction.produceStack(classGen.getConstantPool()) != 1) { + instructionHandle3 = instructionHandle2; + break label176; + } + if (ifInstruction2.consumeStack(classGen.getConstantPool()) != 1) { + instructionHandle3 = instructionHandle2; + break label176; + } + OptimizationStatistics.count12++; + instructionList.createInstructionHandle(instructionHandle, instruction.copy()); + instructionList.createInstructionHandle( + instructionHandle, InstructionConstants.SWAP); + this.processInstructionHandle( + instructionHandle.getInstructionHandle2(), + instructionHandle.getInstructionHandle2().getInstructionHandle2()); + this.processInstructionHandle2( + instructionHandle.getInstructionHandle2(), + instructionHandle.getInstructionHandle2().getInstructionHandle2()); + label106: + { + try { + instructionList.processInstructionHandle2( + instructionHandle.getInstructionHandle2()); + } catch (TargetLostException targetLostException) { + ifInstruction = ifInstruction2; + break label106; + } + ifInstruction = ifInstruction2; + } + ifInstruction.setTarget(instructionHandle5.getInstructionHandle2()); + this.processInstructionHandle( + instructionHandle5, instructionHandle5.getInstructionHandle2()); + this.processInstructionHandle2( + instructionHandle5, instructionHandle5.getInstructionHandle2()); + try { + instructionList.processInstructionHandle2(instructionHandle5); + } catch (TargetLostException targetLostException2) { + break label150; + } + instructionHandle3 = instructionHandle2; + break label176; + } + } + } + instructionHandle3 = instructionHandle2; + } + } + instructionHandle3 = instructionHandle2 = instructionHandle3.getInstructionHandle2(); + } + } + + public void processInstructionList10( + ClassGen classGen, MethodGen methodGen, InstructionList instructionList) { + InstructionHandle instructionHandle; + InstructionHandle instructionHandle2 = instructionHandle = instructionList.getStart(); + while (instructionHandle2 != null) { + if (!(instructionHandle.getInstruction() instanceof Select)) { + instructionHandle2 = instructionHandle; + } else { + label80: + { + Select select; + InstructionHandle[] instructionHandles; + if ((instructionHandles = + (select = (Select) instructionHandle.getInstruction()).getTargets()) + != null) { + if (instructionHandles.length == 0) { + instructionHandle2 = instructionHandle; + break label80; + } + InstructionHandle instructionHandle3 = null; + InstructionHandle instructionHandle4 = null; + InstructionHandle[] instructionHandles2 = instructionHandles; + int value = instructionHandles.length; + int value2; + for (int value3 = value2 = 0; value3 < value; value3 = ++value2) { + InstructionHandle instructionHandle5; + if ((instructionHandle5 = instructionHandles2[value2]) != null + && instructionHandle3 == null + && !(instructionHandle5.getInstruction() instanceof BranchInstruction) + && !(instructionHandle5.getInstruction() instanceof NEW) + && instructionHandle5 != select.getTarget()) { + instructionHandle3 = instructionHandle5; + } + if (instructionHandle5 != null + && instructionHandle5.getInstructionHandle() != null + && (instructionHandle5.getInstructionHandle().getInstruction() instanceof GOTO + || instructionHandle5.getInstructionHandle().getInstruction() + instanceof ReturnInstruction)) { + instructionHandle4 = instructionHandle5.getInstructionHandle(); + } + } + if (instructionHandle3 != null && instructionHandle4 != null) { + instructionList.update(); + if (Math.abs(instructionHandle3.getPosition() - instructionHandle4.getPosition()) + > 32000) { + instructionHandle4 = null; + } + } + if (instructionHandle3 != null && instructionHandle4 != null) { + OptimizationStatistics.count29++; + BranchInstruction branchInstruction = + InstructionFactory.createBranchInstruction((short) 154, null); + instructionList.createBranchHandle(instructionHandle3, branchInstruction); + InstructionHandle instructionHandle6 = + instructionList.createInstructionHandle2(instructionHandle3, new ICONST(0)); + branchInstruction.setTarget( + instructionList.createBranchHandle( + instructionHandle4, new GOTO(instructionHandle6))); + instructionHandle2 = instructionHandle; + break label80; + } + if (instructionHandle3 != null) { + OptimizationStatistics.count29++; + InstructionHandle instructionHandle7 = + instructionList.createInstructionHandle2(instructionHandle3, new ICONST(0)); + instructionList.createBranchHandle(instructionHandle7, new IFNE(instructionHandle7)); + } + } + instructionHandle2 = instructionHandle; + } + } + instructionHandle2 = instructionHandle = instructionHandle2.getInstructionHandle2(); + } + } + + public static long[] getSeeds(long value, int value2) { + long value3 = value; + long value4 = value; + int value5; + for (int value6 = value5 = 0; value6 < value2; value6 = ++value5) { + if ((value >> value5) % 2L == 0L) { + if (RandomUtils.calculateValue() < 0.5) { + value3 |= 1L << value5; + } else { + value4 |= 1L << value5; + } + } + } + return new long[] {value3, value4}; + } + + public void processInstructionList11( + ClassGen classGen, MethodGen methodGen, InstructionList instructionList) { + InstructionHandle instructionHandle; + LocalVariableGen[] localVariableGens; + if ((localVariableGens = methodGen.getLocalVariables()) != null) { + if (localVariableGens.length != 0) { + int value; + if ((value = methodGen.getCount()) >= 4) { + int value2 = methodGen.getArgumentNames().length; + if (!methodGen.isEnabled11()) { + value2++; + } + Type[] types; + int value3 = (types = methodGen.getArgumentTypes()).length; + int value4; + for (int value5 = value4 = 0; value5 < value3; value5 = ++value4) { + Type type; + if ((type = types[value4]) == Type.LONG || type == Type.DOUBLE) { + value2++; + } + } + if (value2 < 4) { + int[] values = new int[value]; + boolean[] matchess = new boolean[value]; + InstructionHandle instructionHandle2; + for (InstructionHandle instructionHandle3 = + instructionHandle2 = instructionList.getStart(); + instructionHandle3 != null; + instructionHandle3 = + instructionHandle2 = instructionHandle2.getInstructionHandle2()) { + if (instructionHandle2.getInstruction() instanceof LoadInstruction + || instructionHandle2.getInstruction() instanceof StoreInstruction) { + LocalVariableInstruction localVariableInstruction = + (LocalVariableInstruction) instructionHandle2.getInstruction(); + int value6; + values[value6 = localVariableInstruction.getIndex()]++; + if ((localVariableInstruction.produceStack(classGen.getConstantPool()) == 2 + || localVariableInstruction.consumeStack(classGen.getConstantPool()) == 2) + && value6 + 1 < value) { + matchess[value6] = true; + matchess[value6 + 1] = true; + } + } + } + int value7; + for (int value8 = value7 = 0; value8 < values.length; value8 = value7) { + int value9 = values[value7] << 16 | value7; + int value10 = value7; + value7++; + values[value10] = value9; + } + Arrays.sort(values, 4, value); + int value11; + for (int value12 = value11 = value2; value12 < 4; value12 = ++value11) { + if (!matchess[value11]) { + int value13 = values[value11] >> 16; + int value14; + for (int value15 = value14 = value - 1; value15 >= 4; value15 = --value14) { + int value16 = values[value14] & 65535; + int value17 = values[value14] >> 16; + if (value16 > 3 && !matchess[value16] && value17 > value13) { + OptimizationStatistics.count24++; + values[value14] = 0; + InstructionHandle instructionHandle4; + InstructionHandle instructionHandle5 = + instructionHandle4 = instructionList.getStart(); + while (instructionHandle5 != null) { + label84: + { + if (instructionHandle4.getInstruction() + instanceof LocalVariableInstruction) { + LocalVariableInstruction localVariableInstruction2; + if ((localVariableInstruction2 = + (LocalVariableInstruction) + instructionHandle4.getInstruction()) + .getIndex() + == value11) { + localVariableInstruction2.setIndex(value16); + } else if (localVariableInstruction2.getIndex() == value16) { + localVariableInstruction2.setIndex(value11); + } + } else if (instructionHandle4.getInstruction() instanceof RET) { + RET rET; + if ((rET = (RET) instructionHandle4.getInstruction()).getIndex() + == value11) { + instructionHandle = instructionHandle4; + rET.setIndex(value16); + break label84; + } + if (rET.getIndex() == value16) { + rET.setIndex(value11); + } + } + instructionHandle = instructionHandle4; + } + instructionHandle5 = + instructionHandle4 = instructionHandle.getInstructionHandle2(); + } + break; + } + } + } + } + } + } + } + } + } + + public void processInstructionList12( + ClassGen classGen, MethodGen methodGen, InstructionList instructionList) { + byte value; + int value2; + InvokeInstruction invokeInstruction; + InstructionHandle instructionHandle; + InstructionHandle instructionHandle2 = instructionHandle = instructionList.getStart(); + while (instructionHandle2 != null) { + if (!(instructionHandle.getInstruction() instanceof InvokeInstruction)) { + instructionHandle2 = instructionHandle; + } else { + InvokeInstruction invokeInstruction2 = + (InvokeInstruction) instructionHandle.getInstruction(); + if (!Configuration.getMethodCallRemovalOptions() + .matchesText( + this.classStorage, + classGen, + methodGen, + invokeInstruction2.getText2(classGen.getConstantPool()), + invokeInstruction2.getText4(classGen.getConstantPool()), + invokeInstruction2.getText3(classGen.getConstantPool()))) { + instructionHandle2 = instructionHandle; + } else { + label238: + { + InstructionHandle instructionHandle3; + ConstantPoolGen constantPoolGen; + label220: + { + constantPoolGen = classGen.getConstantPool(); + int value3 = invokeInstruction2.produceStack(constantPoolGen); + instructionHandle3 = null; + if (value3 > 0) { + if (instructionHandle.getInstructionHandle2() != null + && (instructionHandle.getInstructionHandle2().getInstruction() instanceof POP + || instructionHandle.getInstructionHandle2().getInstruction() + instanceof POP2) + && instructionHandle + .getInstructionHandle2() + .getInstruction() + .consumeStack(constantPoolGen) + == value3) { + instructionHandle3 = instructionHandle.getInstructionHandle2(); + } + if (instructionHandle3 == null) { + instructionHandle3 = instructionHandle; + if (Type.INT.equals(invokeInstruction2.getType2(classGen.getConstantPool())) + || Type.SHORT.equals(invokeInstruction2.getType2(classGen.getConstantPool())) + || Type.BYTE.equals(invokeInstruction2.getType2(classGen.getConstantPool())) + || Type.BOOLEAN.equals( + invokeInstruction2.getType2(classGen.getConstantPool())) + || Type.CHAR.equals( + invokeInstruction2.getType2(classGen.getConstantPool()))) { + instructionList.createInstructionHandle2(instructionHandle3, new ICONST(0)); + } else if (Type.LONG.equals( + invokeInstruction2.getType2(classGen.getConstantPool()))) { + instructionList.createInstructionHandle2(instructionHandle3, new LCONST(0L)); + } else if (Type.FLOAT.equals( + invokeInstruction2.getType2(classGen.getConstantPool()))) { + instructionList.createInstructionHandle2(instructionHandle3, new FCONST(0.0F)); + } else if (Type.DOUBLE.equals( + invokeInstruction2.getType2(classGen.getConstantPool()))) { + instructionList.createInstructionHandle2(instructionHandle3, new DCONST(0.0)); + } else if (invokeInstruction2.getType2(classGen.getConstantPool()) + instanceof ArrayType) { + instructionList.createInstructionHandle2(instructionHandle3, new ACONST_NULL()); + } else { + if (!(invokeInstruction2.getType2(classGen.getConstantPool()) + instanceof ObjectType)) { + Log.warn( + "[remove-calls] Cannot remove call (" + + invokeInstruction2.getText2(constantPoolGen) + + "." + + invokeInstruction2.getText4(constantPoolGen) + + ") in " + + classGen.getClassName() + + "." + + methodGen.getName() + + " - return value is used"); + instructionHandle2 = instructionHandle; + break label238; + } + instructionList.createInstructionHandle2(instructionHandle3, new ACONST_NULL()); + } + Log.warn( + "[remove-calls] return value of " + + invokeInstruction2.getText2(constantPoolGen) + + "." + + invokeInstruction2.getText4(constantPoolGen) + + " in " + + classGen.getClassName() + + "." + + methodGen.getName() + + " was replaced with null(0)"); + invokeInstruction = invokeInstruction2; + break label220; + } + } else { + instructionHandle3 = instructionHandle; + } + invokeInstruction = invokeInstruction2; + } + int value4 = invokeInstruction.consumeStack(constantPoolGen); + InstructionHandle instructionHandle4; + instructionHandle2 = instructionHandle4 = instructionHandle; + while (true) { + if (instructionHandle2.getInstructionHandle() == null) { + value2 = value4; + break; + } + if (value4 == 0) { + value2 = value4; + break; + } + instructionHandle4 = instructionHandle4.getInstructionHandle(); + value4 -= + instructionHandle4.getInstruction().produceStack(constantPoolGen) + - instructionHandle4.getInstruction().consumeStack(constantPoolGen); + instructionHandle2 = instructionHandle4; + } + if (value2 != 0) { + Log.warn( + "[remove-calls] Cannot remove call (" + + invokeInstruction2.getText2(constantPoolGen) + + "." + + invokeInstruction2.getText4(constantPoolGen) + + ") in " + + classGen.getClassName() + + "." + + methodGen.getName() + + " - parameters not found"); + instructionHandle2 = instructionHandle; + } else { + InstructionHandle instructionHandle5 = instructionHandle4; + InstructionHandle instructionHandle6 = instructionHandle4; + int value5 = 0; + label191: + while (true) { + instructionHandle2 = instructionHandle6; + while (instructionHandle2 != instructionHandle3 + && instructionHandle6.getInstructionHandle2() != null) { + instructionHandle6 = instructionHandle6.getInstructionHandle2(); + if (this.matchesInstructionTargeters(instructionHandle6.getTargeters())) { + continue label191; + } + InstructionHandle instructionHandle7 = instructionHandle6; + value5++; + instructionHandle2 = instructionHandle7; + } + if (value5 == 1) { + byte value6 = 0; + InstructionTargeter[] instructionTargeters; + if ((instructionTargeters = instructionHandle3.getTargeters()) != null) { + InstructionTargeter[] instructionTargeters2 = instructionTargeters; + int value7 = instructionTargeters.length; + int value8; + for (int value9 = value8 = 0; value9 < value7; value9 = ++value8) { + InstructionTargeter instructionTargeter; + if (!((instructionTargeter = instructionTargeters2[value8]) + instanceof LineNumberGen) + && !(instructionTargeter instanceof LocalVariableGen) + && instructionTargeter instanceof CodeExceptionGen) { + value6 = 1; + } + } + } + if (value6 != 0 && instructionHandle5 != instructionHandle3) { + instructionHandle3.setInstruction(InstructionConstants.NOP); + instructionHandle3 = instructionHandle3.getInstructionHandle(); + value5 = 0; + } + } + if (value5 > 0) { + Log.warn( + "[remove-calls] Cannot remove call (" + + invokeInstruction2.getText2(constantPoolGen) + + "." + + invokeInstruction2.getText4(constantPoolGen) + + ") in " + + classGen.getClassName() + + "." + + methodGen.getName() + + " - targeters inside block"); + instructionHandle2 = instructionHandle; + } else { + InstructionHandle instructionHandle8; + if ((instructionHandle8 = instructionHandle3.getInstructionHandle2()) == null) { + Log.warn( + "[remove-calls] Cannot remove call (" + + invokeInstruction2.getText2(constantPoolGen) + + "." + + invokeInstruction2.getText4(constantPoolGen) + + ") in " + + classGen.getClassName() + + "." + + methodGen.getName() + + " - unexpected end of block"); + instructionHandle2 = instructionHandle; + } else { + InstructionTargeter[] instructionTargeters3; + if ((instructionTargeters3 = instructionHandle5.getTargeters()) != null) { + InstructionTargeter[] instructionTargeters4 = instructionTargeters3; + int value10 = instructionTargeters3.length; + int value11; + for (int value12 = value11 = 0; value12 < value10; value12 = ++value11) { + InstructionTargeter instructionTargeter2; + if (!((instructionTargeter2 = instructionTargeters4[value11]) + instanceof LineNumberGen) + && !(instructionTargeter2 instanceof LocalVariableGen)) { + instructionTargeter2.updateTarget(instructionHandle5, instructionHandle8); + } + } + } + InstructionHandle instructionHandle9 = instructionHandle8; + do { + instructionHandle9 = instructionHandle9.getInstructionHandle(); + this.processInstructionHandle(instructionHandle9, instructionHandle8); + this.processInstructionHandle2(instructionHandle9, instructionHandle8); + } while (instructionHandle9 != instructionHandle5 + && instructionHandle9.getInstructionHandle() != null); + byte value13 = 0; + InstructionHandle instructionHandle10; + instructionHandle2 = instructionHandle10 = instructionHandle3; + while (true) { + if (instructionHandle2 == instructionHandle5) { + value = value13; + break; + } + if (instructionHandle10.getInstruction() instanceof IfInstruction) { + byte value14 = 1; + instructionHandle5 = instructionHandle10.getInstructionHandle2(); + value = value14; + break; + } + instructionHandle2 = + instructionHandle10 = instructionHandle10.getInstructionHandle(); + } + label145: + if (value == 0) { + try { + instructionList.processInstructionHandle( + instructionHandle5, instructionHandle3); + } catch (TargetLostException targetLostException) { + instructionHandle2 = instructionHandle8; + break label145; + } + instructionHandle2 = instructionHandle8; + } else { + label236: + { + int value15 = + instructionHandle3.getInstruction().consumeStack(constantPoolGen); + InstructionHandle instructionHandle11; + for (InstructionHandle instructionHandle12 = + instructionHandle11 = instructionHandle5; + instructionHandle12 != instructionHandle3; + instructionHandle12 = + instructionHandle11 = instructionHandle11.getInstructionHandle2()) { + value15 -= + instructionHandle11.getInstruction().produceStack(constantPoolGen) + - instructionHandle11 + .getInstruction() + .consumeStack(constantPoolGen); + } + int value16; + for (int value17 = value16 = 0; value17 < value15; value17 = value16) { + value16++; + instructionList.createInstructionHandle2(instructionHandle3, new POP()); + } + try { + instructionList.processInstructionHandle( + instructionHandle5, instructionHandle3); + } catch (TargetLostException targetLostException2) { + instructionHandle2 = instructionHandle8; + break label236; + } + instructionHandle2 = instructionHandle8; + } + } + if (instructionHandle2.getInstructionHandle() != null) { + instructionHandle2 = instructionHandle8.getInstructionHandle(); + } else { + InstructionHandle instructionHandle13 = instructionHandle8; + instructionHandle2 = instructionHandle13; + } + } + } + break; + } + } + } + } + } + instructionHandle2 = instructionHandle = instructionHandle2.getInstructionHandle2(); + } + } + + public void processInstructionList13( + ClassGen classGen, MethodGen methodGen, InstructionList instructionList) { + InstructionList instructionList2; + int value; + InstructionHandle instructionHandle; + InstructionHandle instructionHandle2 = instructionHandle = instructionList.getStart(); + while (instructionHandle2 != null) { + if (!(instructionHandle.getInstruction() instanceof POP) + && !(instructionHandle.getInstruction() instanceof POP2)) { + instructionHandle2 = instructionHandle; + } else if (!this.matchesInstructionTargeters(instructionHandle.getTargeters())) { + instructionHandle2 = instructionHandle; + } else { + boolean matches = instructionHandle.getInstruction() instanceof POP; + ConstantPoolGen constantPool = classGen.getConstantPool(); + int value2 = 0; + int value3 = 0; + InstructionHandle instructionHandle3 = null; + InstructionHandle instructionHandle22 = instructionHandle.getInstructionHandle2(); + while (true) { + if (instructionHandle22 != null) { + Instruction instruction; + if (!((instruction = instructionHandle22.getInstruction()) + instanceof ArithmeticInstruction) + && !(instruction instanceof ArrayInstruction) + && !(instruction instanceof ConversionInstruction) + && !(instruction instanceof ConstantPushInstruction) + && !(instruction instanceof FieldOrMethod) + && !(instruction instanceof LocalVariableInstruction) + && !(instruction instanceof PushInstruction) + && !(instruction instanceof PopInstruction) + && !(instruction instanceof NEW) + && !(instruction instanceof NEWARRAY) + && !(instruction instanceof NOP)) { + value = value3; + break; + } + if (!this.matchesInstructionTargeters(instructionHandle22.getTargeters())) { + value = value3; + break; + } + int value4 = instructionHandle22.getInstruction().produceStack(constantPool); + int value5 = instructionHandle22.getInstruction().consumeStack(constantPool); + if (value4 != -2) { + if (value5 == -2) { + value = value3; + break; + } + int value6; + if ((value6 = value2 - value5) < 0) { + value = value3; + break; + } + if ((value2 = value6 + value4) == 0) { + instructionHandle3 = instructionHandle22; + if (matches && instructionHandle3.getInstruction() instanceof POP) { + value = value3; + break; + } + } + value3++; + instructionHandle22 = instructionHandle22.getInstructionHandle2(); + if (value3 <= 777) { + continue; + } + value = value3; + break; + } + } + value = value3; + break; + } + if (value == 0) { + instructionHandle2 = instructionHandle; + } else if (instructionHandle3 == null) { + instructionHandle2 = instructionHandle; + } else { + label77: + if (matches && instructionHandle3.getInstruction() instanceof POP) { + OptimizationStatistics.count9++; + InstructionHandle instructionHandle23 = instructionHandle.getInstructionHandle2(); + this.processInstructionHandle( + instructionHandle23.getInstructionHandle().getTargeters(), + instructionHandle23.getInstructionHandle(), + instructionHandle23); + label73: + { + try { + instructionList.processInstructionHandle2( + instructionHandle23.getInstructionHandle()); + } catch (TargetLostException targetLostException) { + instructionList2 = instructionList; + this.processInstructionHandle(targetLostException, instructionHandle23); + break label73; + } + instructionList2 = instructionList; + } + instructionList2.createInstructionHandle2( + instructionHandle3, InstructionConstants.POP2); + InstructionHandle instructionHandle24 = instructionHandle3.getInstructionHandle2(); + this.processInstructionHandle( + instructionHandle24.getInstructionHandle().getTargeters(), + instructionHandle24.getInstructionHandle(), + instructionHandle24); + try { + instructionList.processInstructionHandle2(instructionHandle24.getInstructionHandle()); + } catch (TargetLostException targetLostException2) { + instructionHandle2 = instructionHandle23; + this.processInstructionHandle(targetLostException2, instructionHandle24); + break label77; + } + instructionHandle2 = instructionHandle23; + } else { + OptimizationStatistics.count8++; + InstructionHandle instructionHandle25 = instructionHandle.getInstructionHandle2(); + instructionHandle2 = instructionHandle25; + instructionList.processInstructionHandle3( + instructionHandle25.getInstructionHandle(), instructionHandle3); + } + } + } + instructionHandle2 = instructionHandle = instructionHandle2.getInstructionHandle2(); + } + } + + public void processInstructionList14( + ClassGen classGen, MethodGen methodGen, InstructionList instructionList) { + instructionList.update(); + InstructionHandle instructionHandle; + InstructionHandle instructionHandle2 = instructionHandle = instructionList.getStart(); + while (instructionHandle2 != null) { + label107: + { + if (instructionHandle.getInstruction() instanceof GotoInstruction) { + InstructionHandle instructionHandle3; + if ((instructionHandle3 = + ((GotoInstruction) instructionHandle.getInstruction()).getTarget()) + == null) { + instructionHandle2 = instructionHandle; + break label107; + } + if (instructionHandle3 == instructionHandle) { + instructionHandle2 = instructionHandle; + break label107; + } + if (!(instructionHandle3.getInstruction() instanceof GotoInstruction) + && !(instructionHandle3.getInstruction() instanceof ReturnInstruction)) { + instructionHandle2 = instructionHandle; + break label107; + } + if (instructionHandle3.getInstruction() instanceof GotoInstruction) { + int value = 0; + for (InstructionHandle instructionHandle4 = instructionHandle3; + instructionHandle4 != null + && instructionHandle3.getInstruction() instanceof GotoInstruction + && value < 100; + instructionHandle4 = instructionHandle3) { + Instruction instruction = instructionHandle3.getInstruction(); + value++; + instructionHandle3 = ((GotoInstruction) instruction).getTarget(); + } + if (value == 100) { + instructionHandle2 = instructionHandle; + break label107; + } + } + if (instructionHandle3 == null) { + instructionHandle2 = instructionHandle; + break label107; + } + if (instructionHandle3.getInstruction() instanceof ReturnInstruction) { + OptimizationStatistics.count19++; + instructionList.createInstructionHandle2( + instructionHandle, instructionHandle3.getInstruction()); + instructionHandle = instructionHandle.getInstructionHandle2(); + this.processInstructionHandle( + instructionHandle.getInstructionHandle().getTargeters(), + instructionHandle.getInstructionHandle(), + instructionHandle); + try { + instructionList.processInstructionHandle2(instructionHandle.getInstructionHandle()); + } catch (TargetLostException targetLostException) { + this.processInstructionHandle(targetLostException, instructionHandle); + } + } else { + if (Math.abs(instructionHandle.getPosition() - instructionHandle3.getPosition()) + > 32000) { + instructionHandle2 = instructionHandle; + break label107; + } + OptimizationStatistics.count13++; + ((GotoInstruction) instructionHandle.getInstruction()).setTarget(instructionHandle3); + } + } else if (instructionHandle.getInstruction() instanceof IfInstruction) { + InstructionHandle instructionHandle5; + if ((instructionHandle5 = + ((IfInstruction) instructionHandle.getInstruction()).getTarget()) + == null) { + instructionHandle2 = instructionHandle; + break label107; + } + if (!(instructionHandle5.getInstruction() instanceof GotoInstruction)) { + instructionHandle2 = instructionHandle; + break label107; + } + int value2 = 0; + for (InstructionHandle instructionHandle6 = instructionHandle5; + instructionHandle6 != null + && instructionHandle5.getInstruction() instanceof GotoInstruction + && value2 < 100; + instructionHandle6 = instructionHandle5) { + Instruction instruction2 = instructionHandle5.getInstruction(); + value2++; + instructionHandle5 = ((GotoInstruction) instruction2).getTarget(); + } + if (value2 == 100) { + instructionHandle2 = instructionHandle; + break label107; + } + if (instructionHandle5 == null) { + instructionHandle2 = instructionHandle; + break label107; + } + if (Math.abs(instructionHandle.getPosition() - instructionHandle5.getPosition()) + > 32000) { + instructionHandle2 = instructionHandle; + break label107; + } + OptimizationStatistics.count25++; + ((IfInstruction) instructionHandle.getInstruction()).setTarget(instructionHandle5); + } + instructionHandle2 = instructionHandle; + } + instructionHandle2 = instructionHandle = instructionHandle2.getInstructionHandle2(); + } + } + + public void processInstructionList15( + ClassGen classGen, MethodGen methodGen, InstructionList instructionList) { + InstructionHandle instructionHandle; + InstructionHandle instructionHandle2 = instructionHandle = instructionList.getStart(); + while (instructionHandle2 != null) { + if (!(instructionHandle.getInstruction() instanceof ALOAD)) { + instructionHandle2 = instructionHandle; + } else if (!this.matchesInstructionTargeters(instructionHandle.getTargeters())) { + instructionHandle2 = instructionHandle; + } else { + ConstantPoolGen constantPool = classGen.getConstantPool(); + int value = instructionHandle.getInstruction().produceStack(constantPool); + InstructionHandle instructionHandle3 = null; + InstructionHandle instructionHandle22 = instructionHandle.getInstructionHandle2(); + int value2 = 0; + while (true) { + if (instructionHandle22 != null) { + Instruction instruction; + if (!((instruction = instructionHandle22.getInstruction()) + instanceof ArithmeticInstruction) + && !(instruction instanceof ArrayInstruction) + && !(instruction instanceof ConversionInstruction) + && !(instruction instanceof ConstantPushInstruction) + && !(instruction instanceof FieldOrMethod) + && !(instruction instanceof LoadInstruction) + && !(instruction instanceof PushInstruction) + && !(instruction instanceof NEW) + && !(instruction instanceof NEWARRAY) + && !(instruction instanceof NOP) + && !(instruction instanceof POP) + && !(instruction instanceof POP2)) { + instructionHandle2 = instructionHandle3; + break; + } + if (!this.matchesInstructionTargeters(instructionHandle22.getTargeters())) { + instructionHandle2 = instructionHandle3; + break; + } + Instruction instruction2; + if (value == 0 + && ((instruction2 = instructionHandle22.getInstruction()) instanceof LoadInstruction + || instruction2 instanceof ConstantPushInstruction + || instruction2 instanceof LDC + || instruction2 instanceof LDC2_W + || instruction2 instanceof ACONST_NULL)) { + instructionHandle2 = instructionHandle3 = instructionHandle22; + break; + } + int value3 = instructionHandle22.getInstruction().produceStack(constantPool); + int value4 = instructionHandle22.getInstruction().consumeStack(constantPool); + if (value3 != -2) { + if (value4 == -2) { + instructionHandle2 = instructionHandle3; + break; + } + int value5; + if ((value5 = value - value4) < 0) { + instructionHandle2 = instructionHandle3; + break; + } + value = value5 + value3; + instructionHandle22 = instructionHandle22.getInstructionHandle2(); + int value6 = value2++; + if (value6 <= (short) 777) { + continue; + } + instructionHandle2 = instructionHandle3; + break; + } + } + instructionHandle2 = instructionHandle3; + break; + } + if (instructionHandle2 == null) { + instructionHandle2 = instructionHandle; + } else { + OptimizationStatistics.count18++; + this.processInstructionHandle( + instructionHandle3, instructionHandle3.getInstructionHandle2()); + instructionHandle2 = instructionHandle; + instructionList.processInstructionHandle3( + instructionHandle3, instructionHandle.getInstructionHandle()); + } + } + instructionHandle2 = instructionHandle = instructionHandle2.getInstructionHandle2(); + } + } + + public void processInstructionList16( + ClassGen classGen, MethodGen methodGen, InstructionList instructionList) { + InstructionHandle instructionHandle; + InstructionHandle instructionHandle2 = instructionHandle = instructionList.getStart(); + while (instructionHandle2 != null) { + if (!this.matchesInstruction(instructionHandle.getInstruction())) { + instructionHandle2 = instructionHandle; + } else if (!this.matchesInstructionTargeters(instructionHandle.getTargeters())) { + instructionHandle2 = instructionHandle; + } else { + ConstantPoolGen constantPool = classGen.getConstantPool(); + Instruction instruction = instructionHandle.getInstruction(); + int value = 0; + InstructionHandle instructionHandle3 = null; + InstructionHandle instructionHandle4 = null; + InstructionHandle instructionHandle22 = instructionHandle.getInstructionHandle2(); + int value2 = 0; + while (true) { + if (instructionHandle22 != null) { + Instruction instruction2; + if (!((instruction2 = instructionHandle22.getInstruction()) + instanceof ArithmeticInstruction) + && !(instruction2 instanceof ArrayInstruction) + && !(instruction2 instanceof ConversionInstruction) + && !(instruction2 instanceof ConstantPushInstruction) + && !(instruction2 instanceof FieldOrMethod) + && !(instruction2 instanceof LocalVariableInstruction) + && !(instruction2 instanceof PushInstruction) + && !(instruction2 instanceof PopInstruction) + && !(instruction2 instanceof NEW) + && !(instruction2 instanceof NEWARRAY) + && !(instruction2 instanceof NOP)) { + instructionHandle2 = instructionHandle4; + break; + } + if (!this.matchesInstructionTargeters(instructionHandle22.getTargeters())) { + instructionHandle2 = instructionHandle4; + break; + } + if (value == 1) { + Instruction instruction3 = instructionHandle22.getInstruction(); + if (this.matchesInstruction(instruction3) + && this.matchesConstantPoolGen(instruction, instruction3, constantPool)) { + instructionHandle3 = instructionHandle22; + } + } else if (value == 2) { + Instruction instruction4 = instructionHandle22.getInstruction(); + if (this.matchesInstruction(instruction4) + && this.matchesConstantPoolGen(instruction, instruction4, constantPool)) { + instructionHandle2 = instructionHandle4 = instructionHandle22; + break; + } + } + int value3 = instructionHandle22.getInstruction().produceStack(constantPool); + int value4 = instructionHandle22.getInstruction().consumeStack(constantPool); + if (value3 != -2) { + if (value4 == -2) { + instructionHandle2 = instructionHandle4; + break; + } + int value5; + if ((value5 = value - value4) < 0) { + instructionHandle2 = instructionHandle4; + break; + } + value = value5 + value3; + instructionHandle22 = instructionHandle22.getInstructionHandle2(); + int value6 = value2++; + if (value6 <= (short) 777) { + continue; + } + instructionHandle2 = instructionHandle4; + break; + } + } + instructionHandle2 = instructionHandle4; + break; + } + InstructionHandle instructionHandle5 = + instructionHandle2 != null ? instructionHandle4 : instructionHandle3; + int value7 = instructionHandle4 != null ? 2 : 1; + if (instructionHandle5 == null) { + instructionHandle2 = instructionHandle; + } else { + OptimizationStatistics.count17++; + InstructionHandle instructionHandle6; + InstructionHandle instructionHandle7 = + instructionHandle6 = instructionHandle.getInstructionHandle2(); + this.processInstructionHandle( + instructionHandle6.getInstructionHandle(), instructionHandle6); + this.processInstructionHandle2( + instructionHandle7.getInstructionHandle(), instructionHandle5); + label88: + { + try { + instructionList.processInstructionHandle2(instructionHandle6.getInstructionHandle()); + } catch (TargetLostException targetLostException) { + instructionHandle2 = instructionHandle5; + break label88; + } + instructionHandle2 = instructionHandle5; + } + if (instructionHandle2.getInstruction().produceStack(constantPool) == 1) { + if (value7 == 2) { + instructionHandle2 = instructionHandle6; + instructionList.createInstructionHandle2( + instructionHandle5, InstructionConstants.DUP_X2); + } else { + instructionList.createInstructionHandle2( + instructionHandle5, InstructionConstants.DUP_X1); + instructionHandle2 = instructionHandle6; + } + } else { + label137: + { + if (instructionHandle5.getInstruction().produceStack(constantPool) == 2) { + if (value7 == 2) { + instructionHandle2 = instructionHandle6; + instructionList.createInstructionHandle2( + instructionHandle5, InstructionConstants.DUP2_X2); + break label137; + } + instructionList.createInstructionHandle2( + instructionHandle5, InstructionConstants.DUP2_X1); + } + instructionHandle2 = instructionHandle6; + } + } + } + } + instructionHandle2 = instructionHandle = instructionHandle2.getInstructionHandle2(); + } + } + + public void processInstructionList17( + ClassGen classGen, MethodGen methodGen, InstructionList instructionList) { + MethodOptimizer methodOptimizer; + int value; + InstructionHandle instructionHandle; + InstructionHandle instructionHandle2 = instructionHandle = instructionList.getStart(); + while (instructionHandle2 != null) { + if (!(instructionHandle.getInstruction() instanceof LoadInstruction)) { + instructionHandle2 = instructionHandle; + } else if (instructionHandle.getInstructionHandle2() == null) { + instructionHandle2 = instructionHandle; + } else { + InstructionHandle instructionHandle3; + if ((instructionHandle3 = instructionHandle.getInstructionHandle2()).getInstructionHandle2() + == null) { + instructionHandle2 = instructionHandle; + } else { + InstructionHandle instructionHandle4; + if ((instructionHandle4 = instructionHandle3.getInstructionHandle2()) + .getInstructionHandle2() + == null) { + instructionHandle2 = instructionHandle; + } else { + InstructionHandle instructionHandle5; + if ((instructionHandle5 = instructionHandle4.getInstructionHandle2()) + .getInstructionHandle2() + == null) { + instructionHandle2 = instructionHandle; + } else { + InstructionHandle instructionHandle6; + if ((instructionHandle6 = instructionHandle5.getInstructionHandle2()) + .getInstructionHandle2() + == null) { + instructionHandle2 = instructionHandle; + } else { + InstructionHandle instructionHandle22 = instructionHandle6.getInstructionHandle2(); + if (!(instructionHandle3.getInstruction() instanceof StoreInstruction)) { + instructionHandle2 = instructionHandle; + } else if (!(instructionHandle4.getInstruction() instanceof LoadInstruction)) { + instructionHandle2 = instructionHandle; + } else if (!(instructionHandle5.getInstruction() instanceof StoreInstruction)) { + instructionHandle2 = instructionHandle; + } else if (!(instructionHandle6.getInstruction() instanceof LoadInstruction)) { + instructionHandle2 = instructionHandle; + } else if (!(instructionHandle22.getInstruction() instanceof StoreInstruction)) { + instructionHandle2 = instructionHandle; + } else if (((LoadInstruction) instructionHandle.getInstruction()).getIndex() + != ((StoreInstruction) instructionHandle5.getInstruction()).getIndex()) { + instructionHandle2 = instructionHandle; + } else if (((StoreInstruction) instructionHandle3.getInstruction()).getIndex() + != ((LoadInstruction) instructionHandle6.getInstruction()).getIndex()) { + instructionHandle2 = instructionHandle; + } else if (((LoadInstruction) instructionHandle4.getInstruction()).getIndex() + != ((StoreInstruction) instructionHandle22.getInstruction()).getIndex()) { + instructionHandle2 = instructionHandle; + } else { + byte value2 = 1; + InstructionHandle instructionHandle23 = instructionHandle.getInstructionHandle2(); + int value3; + int value4 = value3 = 1; + while (true) { + if (value4 >= 6) { + value = value2; + break; + } + if (!this.matchesInstructionTargeters(instructionHandle23.getTargeters())) { + value = 0; + break; + } + InstructionHandle instructionHandle7 = instructionHandle23; + value3++; + instructionHandle23 = instructionHandle7.getInstructionHandle2(); + value4 = value3; + } + if (value == 0) { + instructionHandle2 = instructionHandle; + } else { + label122: + { + OptimizationStatistics.count28++; + this.processInstructionHandle(instructionHandle3, instructionHandle); + this.processInstructionHandle2(instructionHandle3, instructionHandle); + label91: + { + try { + instructionList.processInstructionHandle2(instructionHandle3); + } catch (TargetLostException targetLostException) { + methodOptimizer = this; + break label91; + } + methodOptimizer = this; + } + methodOptimizer.processInstructionHandle( + instructionHandle6, instructionHandle22); + this.processInstructionHandle2(instructionHandle6, instructionHandle22); + try { + instructionList.processInstructionHandle2(instructionHandle6); + } catch (TargetLostException targetLostException2) { + instructionHandle2 = instructionHandle; + break label122; + } + instructionHandle2 = instructionHandle; + } + } + } + } + } + } + } + } + instructionHandle2 = instructionHandle = instructionHandle2.getInstructionHandle2(); + } + } + + public static int[] getCounts(int value, int value2) { + int value3 = value; + int value4 = value; + int value5; + for (int value6 = value5 = 0; value6 < value2; value6 = ++value5) { + if ((value >> value5) % 2 == 0) { + if (RandomUtils.calculateValue() < 0.5) { + value3 |= 1 << value5; + } else { + value4 |= 1 << value5; + } + } + } + return new int[] {value3, value4}; + } + + public boolean matchesConstantPoolGen( + Instruction instruction, Instruction instruction2, ConstantPoolGen constantPoolGen) { + if (instruction instanceof ConstantPushInstruction + && instruction2 instanceof ConstantPushInstruction) { + if (((ConstantPushInstruction) instruction).getType(constantPoolGen) + == ((ConstantPushInstruction) instruction2).getType(constantPoolGen) + && ((ConstantPushInstruction) instruction) + .getValue() + .equals(((ConstantPushInstruction) instruction2).getValue())) { + return true; + } + } else { + if (instruction instanceof ACONST_NULL && instruction2 instanceof ACONST_NULL) { + return true; + } + if (instruction instanceof LDC && instruction2 instanceof LDC) { + if (((LDC) instruction).getIndex() == ((LDC) instruction2).getIndex()) { + return true; + } + } else if (instruction instanceof LDC2_W && instruction2 instanceof LDC2_W) { + if (((LDC2_W) instruction).getIndex() == ((LDC2_W) instruction2).getIndex()) { + return true; + } + } else if (instruction instanceof GETSTATIC + && instruction2 instanceof GETSTATIC + && ((GETSTATIC) instruction).getIndex() == ((GETSTATIC) instruction2).getIndex()) { + return true; + } + } + return false; + } + + @Override + public void notify(ClassGen classGen) { + Method[] methods = classGen.getMethods(); + int value; + for (int value2 = value = 0; value2 < methods.length; value2 = ++value) { + Method method; + if ((method = methods[value]).getCode() != null) { + MethodGen methodGen = + MethodFactory.createMethodGen( + method, + classGen.getClassName(), + classGen.getConstantPool(), + classGen.getConstantPool().getConstantPool()); + if (!Configuration.getObfuscationOptions() + .matchesMethodGen(this.classStorage, classGen, methodGen)) { + if (Configuration.getMethodCallRemovalOptions().isEnabled()) { + InstructionList instructionList = methodGen.getInstructionList(); + instructionList.update(); + this.processInstructionList12(classGen, methodGen, instructionList); + methodGen.update5(); + methodGen.update4(); + classGen.replaceMethod(method, methodGen.getMethod()); + } + if (Configuration.getFieldRemovalOptions().isValues()) { + InstructionList instructionList2 = methodGen.getInstructionList(); + instructionList2.update(); + this.processInstructionList3(classGen, methodGen, instructionList2); + methodGen.update5(); + methodGen.update4(); + classGen.replaceMethod(method, methodGen.getMethod()); + } + } else { + InstructionList instructionList3; + (instructionList3 = methodGen.getInstructionList()).update(); + if (Configuration.getMethodCallRemovalOptions().isEnabled()) { + this.processInstructionList12(classGen, methodGen, instructionList3); + } + if (Configuration.getFieldRemovalOptions().isValues()) { + this.processInstructionList3(classGen, methodGen, instructionList3); + } + int value3; + value2 = + value3 = + Configuration.getExtensiveFlowOptions() + .calculateCount(this.classStorage, classGen, methodGen); + Configuration.getExtensiveFlowOptions(); + if (value2 != 0 && !method.getText().startsWith("Allatori")) { + this.processInstructionList7(classGen, methodGen, instructionList3); + } + this.processInstructionList20(classGen, methodGen, instructionList3); + this.processInstructionList18(classGen, methodGen, instructionList3); + this.processInstructionList25(classGen, methodGen, instructionList3); + this.processInstructionList17(classGen, methodGen, instructionList3); + this.processInstructionList13(classGen, methodGen, instructionList3); + this.processInstructionList9(classGen, methodGen, instructionList3); + this.processEnabled2(classGen, methodGen, instructionList3, true); + this.processEnabled2(classGen, methodGen, instructionList3, false); + this.processInstructionList15(classGen, methodGen, instructionList3); + this.processEnabled(classGen, methodGen, instructionList3, false); + this.processInstructionList2(classGen, methodGen, instructionList3); + this.processInstructionList27(classGen, methodGen, instructionList3); + this.processEnabled(classGen, methodGen, instructionList3, true); + this.processInstructionList16(classGen, methodGen, instructionList3); + this.processInstructionList16(classGen, methodGen, instructionList3); + this.processInstructionList26(classGen, methodGen, instructionList3); + this.processInstructionList(classGen, methodGen, instructionList3); + this.processInstructionList19(classGen, methodGen, instructionList3); + this.processInstructionList6(classGen, methodGen, instructionList3); + this.processInstructionList14(classGen, methodGen, instructionList3); + this.processInstructionList8(classGen, methodGen, instructionList3); + this.processInstructionList5(classGen, methodGen, instructionList3); + this.processInstructionList21(classGen, methodGen, instructionList3); + this.processInstructionList11(classGen, methodGen, instructionList3); + Configuration.getExtensiveFlowOptions(); + if (value3 != 0) { + this.processInstructionList23(classGen, methodGen, instructionList3); + } + this.processInstructionList10(classGen, methodGen, instructionList3); + Configuration.getExtensiveFlowOptions(); + if (value3 == 1) { + this.processCount( + classGen, methodGen, instructionList3, 20, 16, 16, 20, 16, 16, 8, 4, 4); + } else { + Configuration.getExtensiveFlowOptions(); + if (value3 == 2) { + this.processCount( + classGen, methodGen, instructionList3, 64, 32, 32, 64, 32, 64, 32, 8, 8); + } else if (Configuration.getObfuscationOptions().isEnabled3() + && Configuration.getObfuscationOptions().isMethodsNamingEnabled()) { + this.processCount(classGen, methodGen, instructionList3, 8, 4, 4, 8, 4, 4, 4, 2, 2); + } + } + if (Configuration.getMethodRemovalOptions() + .matchesMethod(this.classStorage, classGen, method)) { + this.processInstructionList4(classGen, methodGen, instructionList3); + } + methodGen.update5(); + methodGen.update4(); + classGen.replaceMethod(method, methodGen.getMethod()); + } + } + } + } + + public void processInstructionList18( + ClassGen classGen, MethodGen methodGen, InstructionList instructionList) { + InstructionHandle instructionHandle; + InstructionHandle instructionHandle2 = instructionHandle = instructionList.getStart(); + while (instructionHandle2 != null) { + if (!(instructionHandle.getInstruction() instanceof GotoInstruction)) { + instructionHandle2 = instructionHandle; + } else if (!this.matchesInstructionTargeters(instructionHandle.getTargeters())) { + instructionHandle2 = instructionHandle; + } else { + label27: + { + GotoInstruction gotoInstruction; + InstructionHandle instructionHandle3; + if ((instructionHandle3 = + (gotoInstruction = (GotoInstruction) instructionHandle.getInstruction()) + .getTarget()) + != null) { + if (instructionHandle3.getInstructionHandle2() == null) { + instructionHandle2 = instructionHandle; + break label27; + } + if (!(instructionHandle3.getInstruction() instanceof LoadInstruction)) { + instructionHandle2 = instructionHandle; + break label27; + } + gotoInstruction.setTarget(instructionHandle3.getInstructionHandle2()); + instructionList.createInstructionHandle2( + gotoInstruction, instructionHandle3.getInstruction().copy()); + OptimizationStatistics.count26++; + } + instructionHandle2 = instructionHandle; + } + } + instructionHandle2 = instructionHandle = instructionHandle2.getInstructionHandle2(); + } + } + + public void processCount( + ClassGen classGen, + MethodGen methodGen, + InstructionList instructionList, + int value, + int value2, + int value3, + int value4, + int value5, + int value6, + int value7, + int value8, + int value9) { + InstructionList instructionList2; + InstructionList instructionList3; + InstructionList instructionList4; + InstructionList instructionList5; + InstructionList instructionList6; + InstructionList instructionList7; + InstructionList instructionList8; + InstructionList instructionList9; + InstructionList instructionList10; + InstructionList instructionList11; + InstructionList instructionList12; + InstructionList instructionList13; + InstructionList instructionList14; + InstructionList instructionList15; + InstructionList instructionList16; + this.processCount(classGen, methodGen, instructionList, value4); + int value10 = 0; + int value11 = 0; + int value12 = 0; + int value13 = 0; + int value14 = 0; + int value15 = 0; + int value16 = 0; + int value17 = 0; + InstructionHandle instructionHandle; + InstructionHandle instructionHandle2 = instructionHandle = instructionList.getStart(); + while (instructionHandle2 != null + && (value10 < value || value11 < value2 || value12 < value3)) { + if (!this.matchesInstructionTargeters(instructionHandle.getTargeters())) { + instructionHandle2 = instructionHandle; + } else if (instructionHandle.getInstruction() == InstructionConstants.ICONST_0) { + if (value10 >= value) { + instructionHandle2 = instructionHandle; + } else { + int value18; + InstructionHandle instructionHandle3; + InstructionHandle instructionHandle4; + MethodOptimizer methodOptimizer; + if ((value18 = RandomUtils.calculateCount(5)) == 0) { + instructionHandle3 = + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.IAND); + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.ICONST_5); + instructionHandle4 = + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.ICONST_2); + methodOptimizer = this; + } else if (value18 == 1) { + instructionHandle3 = + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.ISHR); + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.ICONST_2); + instructionHandle4 = + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.ICONST_3); + methodOptimizer = this; + } else if (value18 == 2) { + instructionHandle3 = + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.ISHR); + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.ICONST_3); + instructionHandle4 = + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.ICONST_5); + methodOptimizer = this; + } else if (value18 == 3) { + instructionHandle3 = + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.IAND); + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.ICONST_4); + instructionHandle4 = + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.ICONST_3); + methodOptimizer = this; + } else { + instructionHandle3 = + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.IXOR); + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.ICONST_3); + instructionHandle4 = + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.ICONST_3); + methodOptimizer = this; + } + methodOptimizer.processInstructionHandle(instructionHandle, instructionHandle4); + label580: + { + label565: + { + try { + this.processInstructionHandle2(instructionHandle, instructionHandle3); + } catch (ClassGenException classGenException) { + { + instructionList16 = instructionList; + break label565; + } + } + instructionList16 = instructionList; + } + try { + instructionList16.processInstructionHandle2(instructionHandle); + } catch (TargetLostException targetLostException) { + instructionHandle2 = instructionHandle3; + break label580; + } + instructionHandle2 = instructionHandle3; + } + InstructionHandle instructionHandle5 = instructionHandle2; + value10++; + instructionHandle2 = instructionHandle5; + } + } else if (instructionHandle.getInstruction() == InstructionConstants.ICONST_1) { + if (value10 >= value) { + instructionHandle2 = instructionHandle; + } else if (instructionHandle.getInstructionHandle2() != null + && instructionHandle.getInstructionHandle2().getInstructionHandle2() != null + && instructionHandle.getInstructionHandle2().getInstruction() + == InstructionConstants.DUP + && instructionHandle.getInstructionHandle2().getInstructionHandle2().getInstruction() + == InstructionConstants.POP2) { + instructionHandle2 = instructionHandle; + } else { + int value19; + InstructionHandle instructionHandle6; + InstructionHandle instructionHandle7; + MethodOptimizer methodOptimizer2; + if ((value19 = RandomUtils.calculateCount(7)) == 0) { + instructionHandle6 = + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.IAND); + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.ICONST_5); + instructionHandle7 = + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.ICONST_3); + methodOptimizer2 = this; + } else if (value19 == 1) { + instructionHandle6 = + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.ISHR); + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.ICONST_1); + instructionHandle7 = + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.ICONST_3); + methodOptimizer2 = this; + } else if (value19 == 2) { + instructionHandle6 = + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.ISHR); + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.ICONST_2); + instructionHandle7 = + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.ICONST_5); + methodOptimizer2 = this; + } else if (value19 == 3) { + instructionHandle6 = + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.IXOR); + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.ICONST_3); + instructionHandle7 = + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.ICONST_2); + methodOptimizer2 = this; + } else if (value19 != 4 && value19 != 5) { + instructionHandle6 = + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.IXOR); + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.ICONST_5); + instructionHandle7 = + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.ICONST_4); + methodOptimizer2 = this; + } else { + instructionHandle6 = + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.INEG); + instructionHandle7 = + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.ICONST_M1); + methodOptimizer2 = this; + } + methodOptimizer2.processInstructionHandle(instructionHandle, instructionHandle7); + label583: + { + label533: + { + try { + this.processInstructionHandle2(instructionHandle, instructionHandle6); + } catch (ClassGenException classGenException2) { + { + instructionList15 = instructionList; + break label533; + } + } + instructionList15 = instructionList; + } + try { + instructionList15.processInstructionHandle2(instructionHandle); + } catch (TargetLostException targetLostException2) { + instructionHandle2 = instructionHandle6; + break label583; + } + instructionHandle2 = instructionHandle6; + } + InstructionHandle instructionHandle8 = instructionHandle2; + value10++; + instructionHandle2 = instructionHandle8; + } + } else if (instructionHandle.getInstruction() == InstructionConstants.ICONST_2) { + if (value11 >= value2) { + instructionHandle2 = instructionHandle; + } else { + InstructionHandle instructionHandle9; + InstructionHandle instructionHandle10; + int value20; + MethodOptimizer methodOptimizer3; + if ((value20 = RandomUtils.calculateCount(3)) == 0) { + instructionHandle9 = + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.ISHR); + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.ICONST_1); + instructionHandle10 = + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.ICONST_5); + methodOptimizer3 = this; + } else if (value20 == 1) { + instructionHandle9 = + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.INEG); + instructionHandle10 = + instructionList.getInstructionHandle2( + instructionHandle, new PUSH(classGen.getConstantPool(), -2)); + methodOptimizer3 = this; + } else { + instructionHandle9 = + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.IXOR); + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.ICONST_3); + instructionHandle10 = + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.ICONST_1); + methodOptimizer3 = this; + } + methodOptimizer3.processInstructionHandle(instructionHandle, instructionHandle10); + label585: + { + label520: + { + try { + this.processInstructionHandle2(instructionHandle, instructionHandle9); + } catch (ClassGenException classGenException3) { + { + instructionList14 = instructionList; + break label520; + } + } + instructionList14 = instructionList; + } + try { + instructionList14.processInstructionHandle2(instructionHandle); + } catch (TargetLostException targetLostException3) { + instructionHandle2 = instructionHandle9; + break label585; + } + instructionHandle2 = instructionHandle9; + } + InstructionHandle instructionHandle11 = instructionHandle2; + value11++; + instructionHandle2 = instructionHandle11; + } + } else if (instructionHandle.getInstruction() == InstructionConstants.ICONST_3) { + if (value11 >= value2) { + instructionHandle2 = instructionHandle; + } else { + InstructionHandle instructionHandle12 = + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.INEG); + InstructionHandle instructionHandle22 = + instructionList.getInstructionHandle2( + instructionHandle, new PUSH(classGen.getConstantPool(), -3)); + this.processInstructionHandle(instructionHandle, instructionHandle22); + label587: + { + label507: + { + try { + this.processInstructionHandle2(instructionHandle, instructionHandle12); + } catch (ClassGenException classGenException4) { + { + instructionList13 = instructionList; + break label507; + } + } + instructionList13 = instructionList; + } + try { + instructionList13.processInstructionHandle2(instructionHandle); + } catch (TargetLostException targetLostException4) { + instructionHandle2 = instructionHandle12; + break label587; + } + instructionHandle2 = instructionHandle12; + } + InstructionHandle instructionHandle13 = instructionHandle2; + value11++; + instructionHandle2 = instructionHandle13; + } + } else if (instructionHandle.getInstruction() == InstructionConstants.ICONST_4) { + if (value11 >= value2) { + instructionHandle2 = instructionHandle; + } else { + InstructionHandle instructionHandle14 = + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.INEG); + InstructionHandle instructionHandle23 = + instructionList.getInstructionHandle2( + instructionHandle, new PUSH(classGen.getConstantPool(), -4)); + this.processInstructionHandle(instructionHandle, instructionHandle23); + label589: + { + label494: + { + try { + this.processInstructionHandle2(instructionHandle, instructionHandle14); + } catch (ClassGenException classGenException5) { + { + instructionList12 = instructionList; + break label494; + } + } + instructionList12 = instructionList; + } + try { + instructionList12.processInstructionHandle2(instructionHandle); + } catch (TargetLostException targetLostException5) { + instructionHandle2 = instructionHandle14; + break label589; + } + instructionHandle2 = instructionHandle14; + } + InstructionHandle instructionHandle15 = instructionHandle2; + value11++; + instructionHandle2 = instructionHandle15; + } + } else if (instructionHandle.getInstruction() == InstructionConstants.ICONST_5) { + if (value11 >= value2) { + instructionHandle2 = instructionHandle; + } else { + InstructionHandle instructionHandle16 = + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.INEG); + InstructionHandle instructionHandle24 = + instructionList.getInstructionHandle2( + instructionHandle, new PUSH(classGen.getConstantPool(), -5)); + this.processInstructionHandle(instructionHandle, instructionHandle24); + label591: + { + label481: + { + try { + this.processInstructionHandle2(instructionHandle, instructionHandle16); + } catch (ClassGenException classGenException6) { + { + instructionList11 = instructionList; + break label481; + } + } + instructionList11 = instructionList; + } + try { + instructionList11.processInstructionHandle2(instructionHandle); + } catch (TargetLostException targetLostException6) { + instructionHandle2 = instructionHandle16; + break label591; + } + instructionHandle2 = instructionHandle16; + } + InstructionHandle instructionHandle17 = instructionHandle2; + value11++; + instructionHandle2 = instructionHandle17; + } + } else if (instructionHandle.getInstruction() == InstructionConstants.ICONST_M1) { + if (value11 >= value2) { + instructionHandle2 = instructionHandle; + } else { + InstructionHandle instructionHandle18 = + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.ISHR); + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.ICONST_2); + InstructionHandle instructionHandle25 = + instructionList.getInstructionHandle2( + instructionHandle, new PUSH(classGen.getConstantPool(), -4)); + this.processInstructionHandle(instructionHandle, instructionHandle25); + label593: + { + label468: + { + try { + this.processInstructionHandle2(instructionHandle, instructionHandle18); + } catch (ClassGenException classGenException7) { + { + instructionList10 = instructionList; + break label468; + } + } + instructionList10 = instructionList; + } + try { + instructionList10.processInstructionHandle2(instructionHandle); + } catch (TargetLostException targetLostException7) { + instructionHandle2 = instructionHandle18; + break label593; + } + instructionHandle2 = instructionHandle18; + } + InstructionHandle instructionHandle19 = instructionHandle2; + value11++; + instructionHandle2 = instructionHandle19; + } + } else { + label460: + { + if (instructionHandle.getInstruction() instanceof ConstantPushInstruction) { + if (value12 >= value3) { + instructionHandle2 = instructionHandle; + break label460; + } + ConstantPoolGen constantPool = classGen.getConstantPool(); + ConstantPushInstruction constantPushInstruction; + if ((constantPushInstruction = + (ConstantPushInstruction) instructionHandle.getInstruction()) + .getType(constantPool) + != Type.BYTE + && constantPushInstruction.getType(constantPool) != Type.SHORT) { + if (constantPushInstruction.getType(constantPool) != Type.CHAR + && constantPushInstruction.getType(constantPool) != Type.INT + && constantPushInstruction.getType(constantPool) == Type.LONG) {} + } else { + byte value21 = 7; + if (constantPushInstruction.getType(constantPool) == Type.SHORT) { + value21 = 15; + } + int value22; + int[] counts = + getCounts(value22 = constantPushInstruction.getValue().intValue(), value21); + int value23 = counts[0]; + int value24 = counts[1]; + if ((value23 & value24) != value22) { + instructionHandle2 = instructionHandle; + break label460; + } + InstructionHandle instructionHandle20 = + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.IAND); + instructionList.getInstructionHandle2( + instructionHandle, new PUSH(classGen.getConstantPool(), value23)); + InstructionHandle instructionHandle26 = + instructionList.getInstructionHandle2( + instructionHandle, new PUSH(classGen.getConstantPool(), value24)); + this.processInstructionHandle(instructionHandle, instructionHandle26); + label595: + { + label447: + { + try { + this.processInstructionHandle2(instructionHandle, instructionHandle20); + } catch (ClassGenException classGenException8) { + { + instructionList9 = instructionList; + break label447; + } + } + instructionList9 = instructionList; + } + try { + instructionList9.processInstructionHandle2(instructionHandle); + } catch (TargetLostException targetLostException8) { + instructionHandle2 = instructionHandle20; + break label595; + } + instructionHandle2 = instructionHandle20; + } + instructionHandle = instructionHandle2; + value12++; + } + } else if (instructionHandle.getInstruction() instanceof LDC) { + LDC lDC = (LDC) instructionHandle.getInstruction(); + ConstantPoolGen constantPool2 = classGen.getConstantPool(); + if (lDC.getType(constantPool2) == Type.INT) { + int value25 = (Integer) lDC.getValue(constantPool2); + int value26 = 0; + int value27 = value25; + while (value27 > 0 && (value25 & 1) == 0) { + int value28 = value25 >> 1; + value26++; + value27 = value25 = value28; + } + if (value25 == (short) value25 && value26 > 0 && value13 < value5) { + InstructionHandle instructionHandle21 = + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.ISHL); + instructionList.getInstructionHandle2( + instructionHandle, new PUSH(classGen.getConstantPool(), value26)); + InstructionHandle instructionHandle27 = + instructionList.getInstructionHandle2( + instructionHandle, new PUSH(classGen.getConstantPool(), value25)); + this.processInstructionHandle(instructionHandle, instructionHandle27); + label599: + { + label421: + { + try { + this.processInstructionHandle2(instructionHandle, instructionHandle21); + } catch (ClassGenException classGenException9) { + { + instructionList8 = instructionList; + break label421; + } + } + instructionList8 = instructionList; + } + try { + instructionList8.processInstructionHandle2(instructionHandle); + } catch (TargetLostException targetLostException9) { + instructionHandle2 = instructionHandle21; + break label599; + } + instructionHandle2 = instructionHandle21; + } + instructionHandle = instructionHandle2; + value13++; + } else if (value26 > 0 && value16 < value8) { + InstructionHandle instructionHandle28 = + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.ISHL); + instructionList.getInstructionHandle2( + instructionHandle, new PUSH(classGen.getConstantPool(), value26)); + InstructionHandle instructionHandle29 = + instructionList.getInstructionHandle2( + instructionHandle, new PUSH(classGen.getConstantPool(), value25)); + this.processInstructionHandle(instructionHandle, instructionHandle29); + label601: + { + label406: + { + try { + this.processInstructionHandle2(instructionHandle, instructionHandle28); + } catch (ClassGenException classGenException10) { + { + instructionList7 = instructionList; + break label406; + } + } + instructionList7 = instructionList; + } + try { + instructionList7.processInstructionHandle2(instructionHandle); + } catch (TargetLostException targetLostException10) { + instructionHandle2 = instructionHandle28; + break label601; + } + instructionHandle2 = instructionHandle28; + } + instructionHandle = instructionHandle2; + value16++; + } else if (value26 == 0 && value16 < value8) { + int value29 = RandomUtils.calculateCount(32000) + 555; + int value30; + int value31; + if (((value31 = (value30 = (Integer) lDC.getValue(constantPool2)) ^ value29) + ^ value29) + != value30) { + instructionHandle2 = instructionHandle; + break label460; + } + InstructionHandle instructionHandle30 = + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.IXOR); + instructionList.getInstructionHandle2( + instructionHandle, new PUSH(classGen.getConstantPool(), value29)); + InstructionHandle instructionHandle210 = + instructionList.getInstructionHandle2( + instructionHandle, new PUSH(classGen.getConstantPool(), value31)); + this.processInstructionHandle(instructionHandle, instructionHandle210); + label603: + { + label391: + { + try { + this.processInstructionHandle2(instructionHandle, instructionHandle30); + } catch (ClassGenException classGenException11) { + { + instructionList6 = instructionList; + break label391; + } + } + instructionList6 = instructionList; + } + try { + instructionList6.processInstructionHandle2(instructionHandle); + } catch (TargetLostException targetLostException11) { + instructionHandle2 = instructionHandle30; + break label603; + } + instructionHandle2 = instructionHandle30; + } + instructionHandle = instructionHandle2; + value16++; + } + } + } else if (instructionHandle.getInstruction() instanceof LDC2_W) { + LDC2_W lDC2_W = (LDC2_W) instructionHandle.getInstruction(); + ConstantPoolGen constantPool3 = classGen.getConstantPool(); + if (lDC2_W.getType(constantPool3) == Type.LONG) { + long value32 = lDC2_W.getValue(constantPool3).longValue(); + int value33 = 0; + long value34 = value32; + while (value34 > 0L && (value32 & 1L) == 0L) { + long value35 = value32 >> 1; + value33++; + value34 = value32 = value35; + } + if (value32 == (short) value32 && value33 > 0 && value14 < value6) { + InstructionHandle instructionHandle31 = + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.LSHL); + instructionList.getInstructionHandle2( + instructionHandle, new PUSH(classGen.getConstantPool(), value33)); + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.I2L); + InstructionHandle instructionHandle211 = + instructionList.getInstructionHandle2( + instructionHandle, new PUSH(classGen.getConstantPool(), (int) value32)); + this.processInstructionHandle(instructionHandle, instructionHandle211); + label607: + { + label342: + { + try { + this.processInstructionHandle2(instructionHandle, instructionHandle31); + } catch (ClassGenException classGenException12) { + { + instructionList5 = instructionList; + break label342; + } + } + instructionList5 = instructionList; + } + try { + instructionList5.processInstructionHandle2(instructionHandle); + } catch (TargetLostException targetLostException12) { + instructionHandle2 = instructionHandle31; + break label607; + } + instructionHandle2 = instructionHandle31; + } + InstructionHandle instructionHandle32 = instructionHandle2; + value14 += 1; + instructionHandle2 = instructionHandle32; + break label460; + } + if (value32 == (int) value32 && value33 > 0 && value15 < value7) { + InstructionHandle instructionHandle33 = + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.LSHL); + instructionList.getInstructionHandle2( + instructionHandle, new PUSH(classGen.getConstantPool(), value33)); + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.I2L); + InstructionHandle instructionHandle212 = + instructionList.getInstructionHandle2( + instructionHandle, new PUSH(classGen.getConstantPool(), (int) value32)); + this.processInstructionHandle(instructionHandle, instructionHandle212); + label609: + { + label331: + { + try { + this.processInstructionHandle2(instructionHandle, instructionHandle33); + } catch (ClassGenException classGenException13) { + { + instructionList4 = instructionList; + break label331; + } + } + instructionList4 = instructionList; + } + try { + instructionList4.processInstructionHandle2(instructionHandle); + } catch (TargetLostException targetLostException13) { + instructionHandle2 = instructionHandle33; + break label609; + } + instructionHandle2 = instructionHandle33; + } + InstructionHandle instructionHandle34 = instructionHandle2; + value15++; + instructionHandle2 = instructionHandle34; + break label460; + } + if (value33 > 0 && value17 < value9) { + InstructionHandle instructionHandle35 = + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.LSHL); + instructionList.getInstructionHandle2( + instructionHandle, new PUSH(classGen.getConstantPool(), value33)); + InstructionHandle instructionHandle213 = + instructionList.getInstructionHandle2( + instructionHandle, new PUSH(classGen.getConstantPool(), value32)); + this.processInstructionHandle(instructionHandle, instructionHandle213); + label611: + { + label320: + { + try { + this.processInstructionHandle2(instructionHandle, instructionHandle35); + } catch (ClassGenException classGenException14) { + { + instructionList3 = instructionList; + break label320; + } + } + instructionList3 = instructionList; + } + try { + instructionList3.processInstructionHandle2(instructionHandle); + } catch (TargetLostException targetLostException14) { + instructionHandle2 = instructionHandle35; + break label611; + } + instructionHandle2 = instructionHandle35; + } + InstructionHandle instructionHandle36 = instructionHandle2; + value17++; + instructionHandle2 = instructionHandle36; + break label460; + } + if (value33 == 0 && value17 < value9) { + int value36 = RandomUtils.calculateCount(32000) + 555; + long value37; + long value38; + if (((value37 = (value38 = lDC2_W.getValue(constantPool3).longValue()) ^ value36) + ^ value36) + != value38) { + instructionHandle2 = instructionHandle; + break label460; + } + InstructionHandle instructionHandle37 = + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.LXOR); + instructionList.createInstructionHandle2( + instructionHandle, InstructionConstants.I2L); + instructionList.getInstructionHandle2( + instructionHandle, new PUSH(classGen.getConstantPool(), value36)); + InstructionHandle instructionHandle214 = + instructionList.getInstructionHandle2( + instructionHandle, new PUSH(classGen.getConstantPool(), value37)); + this.processInstructionHandle(instructionHandle, instructionHandle214); + label613: + { + label362: + { + try { + this.processInstructionHandle2(instructionHandle, instructionHandle37); + } catch (ClassGenException classGenException15) { + { + instructionList2 = instructionList; + break label362; + } + } + instructionList2 = instructionList; + } + try { + instructionList2.processInstructionHandle2(instructionHandle); + } catch (TargetLostException targetLostException15) { + instructionHandle2 = instructionHandle37; + break label613; + } + instructionHandle2 = instructionHandle37; + } + instructionHandle = instructionHandle2; + value17++; + } + } + } + instructionHandle2 = instructionHandle; + } + } + instructionHandle2 = instructionHandle = instructionHandle2.getInstructionHandle2(); + } + OptimizationStatistics.count22 += value10; + OptimizationStatistics.count15 += value11; + OptimizationStatistics.count21 += value12; + } + + public void processInstructionList19( + ClassGen classGen, MethodGen methodGen, InstructionList instructionList) { + InstructionList instructionList2; + InstructionHandle instructionHandle; + InstructionHandle instructionHandle2 = instructionHandle = instructionList.getStart(); + while (instructionHandle2 != null) { + if (!(instructionHandle.getInstruction() instanceof StoreInstruction)) { + instructionHandle2 = instructionHandle; + } else if (instructionHandle.getInstructionHandle2() == null) { + instructionHandle2 = instructionHandle; + } else if (!(instructionHandle.getInstructionHandle2().getInstruction() + instanceof LoadInstruction)) { + instructionHandle2 = instructionHandle; + } else { + InstructionHandle instructionHandle3 = instructionHandle; + InstructionHandle instructionHandle22 = instructionHandle.getInstructionHandle2(); + StoreInstruction storeInstruction = (StoreInstruction) instructionHandle3.getInstruction(); + LoadInstruction loadInstruction = (LoadInstruction) instructionHandle22.getInstruction(); + if (storeInstruction.getIndex() != loadInstruction.getIndex()) { + instructionHandle2 = instructionHandle; + } else if (!this.matchesInstructionTargeters(instructionHandle22.getTargeters())) { + instructionHandle2 = instructionHandle; + } else if (!this.matchesInstructionTargeters(instructionHandle3.getTargeters())) { + instructionHandle2 = instructionHandle; + } else { + InstructionHandle instructionHandle4; + if ((instructionHandle4 = instructionHandle22.getInstructionHandle2()) == null) { + instructionHandle2 = instructionHandle; + } else { + InstructionHandle instructionHandle5 = instructionHandle4; + label67: + if (this.matchesInstructionHandle( + instructionList, instructionHandle3, instructionHandle22)) { + OptimizationStatistics.count3++; + this.processInstructionHandle(instructionHandle22, instructionHandle4); + this.processInstructionHandle(instructionHandle3, instructionHandle4); + this.processInstructionHandle2(instructionHandle22, instructionHandle4); + this.processInstructionHandle2(instructionHandle3, instructionHandle4); + label64: + { + try { + instructionList.processInstructionHandle2(instructionHandle3); + } catch (TargetLostException targetLostException) { + { + instructionList2 = instructionList; + break label64; + } + } + instructionList2 = instructionList; + } + try { + instructionList2.processInstructionHandle2(instructionHandle22); + } catch (TargetLostException targetLostException2) { + instructionHandle2 = instructionHandle5; + break label67; + } + instructionHandle2 = instructionHandle5; + } else { + label104: + { + OptimizationStatistics.count2++; + MethodOptimizer methodOptimizer; + if (!(storeInstruction instanceof ASTORE) + && !(storeInstruction instanceof FSTORE) + && !(storeInstruction instanceof ISTORE)) { + if (storeInstruction instanceof DSTORE || storeInstruction instanceof LSTORE) { + instructionList.createInstructionHandle( + instructionHandle3, InstructionConstants.DUP2); + } + methodOptimizer = this; + } else { + instructionList.createInstructionHandle( + instructionHandle3, InstructionConstants.DUP); + methodOptimizer = this; + } + methodOptimizer.processInstructionHandle(instructionHandle22, instructionHandle4); + this.processInstructionHandle2(instructionHandle22, instructionHandle3); + try { + instructionList.processInstructionHandle2(instructionHandle22); + } catch (TargetLostException targetLostException3) { + instructionHandle2 = instructionHandle5; + break label104; + } + instructionHandle2 = instructionHandle5; + } + } + } + } + } + instructionHandle2 = instructionHandle = instructionHandle2.getInstructionHandle2(); + } + } + + public MethodOptimizer(ClassStorage classStorage2) { + super(); + this.classStorage = classStorage2; + } + + public void processInstructionHandle( + TargetLostException targetLostException, InstructionHandle instructionHandle) { + InstructionHandle[] targets = targetLostException.getTargets(); + int value; + for (int value2 = value = 0; value2 < targets.length; value2 = ++value) { + int value3; + InstructionTargeter[] instructionTargeters; + if ((instructionTargeters = targets[value].getTargeters()) != null) { + for (int value4 = value3 = 0; value4 < instructionTargeters.length; value4 = value3) { + InstructionTargeter instructionTargeter = instructionTargeters[value3]; + int value5 = value; + value3++; + instructionTargeter.updateTarget(targets[value5], instructionHandle); + } + } + } + } + + public void processInstructionHandle( + InstructionHandle instructionHandle, InstructionHandle instructionHandle2) { + if (instructionHandle2 != null) { + if (instructionHandle.getTargeters() != null) { + if (instructionHandle2.getTargeters() != null) { + InstructionTargeter[] instructionTargeters; + int value = (instructionTargeters = instructionHandle2.getTargeters()).length; + int value2; + for (int value3 = value2 = 0; value3 < value; value3 = ++value2) { + if (instructionTargeters[value2] instanceof LineNumberGen) { + return; + } + } + } + InstructionTargeter[] instructionTargeters2; + int value4 = (instructionTargeters2 = instructionHandle.getTargeters()).length; + int value5; + for (int value6 = value5 = 0; value6 < value4; value6 = ++value5) { + InstructionTargeter instructionTargeter; + if ((instructionTargeter = instructionTargeters2[value5]) instanceof LineNumberGen) { + instructionTargeter.updateTarget(instructionHandle, instructionHandle2); + } + } + } + } + } + + public void processInstructionList20( + ClassGen classGen, MethodGen methodGen, InstructionList instructionList) { + InstructionHandle instructionHandle; + InstructionHandle instructionHandle2 = instructionHandle = instructionList.getStart(); + while (instructionHandle2 != null) { + if (!(instructionHandle.getInstruction() instanceof NEW)) { + instructionHandle2 = instructionHandle; + } else { + String className = + ((NEW) instructionHandle.getInstruction()) + .getLoadClassType(classGen.getConstantPool()) + .getClassName(); + if (!"java.lang.StringBuffer".equals(className) + && !"java.lang.StringBuilder".equals(className)) { + instructionHandle2 = instructionHandle; + } else { + String text = "L" + className.replace('.', '/') + ";"; + if (instructionHandle.getInstructionHandle2() == null) { + instructionHandle2 = instructionHandle; + } else if (!(instructionHandle.getInstructionHandle2().getInstruction() instanceof DUP)) { + instructionHandle2 = instructionHandle; + } else if (instructionHandle.getInstructionHandle2().getInstructionHandle2() == null) { + instructionHandle2 = instructionHandle; + } else if (!(instructionHandle + .getInstructionHandle2() + .getInstructionHandle2() + .getInstruction() + instanceof INVOKESPECIAL)) { + instructionHandle2 = instructionHandle; + } else { + INVOKESPECIAL nVOKESPECIAL = + (INVOKESPECIAL) + instructionHandle + .getInstructionHandle2() + .getInstructionHandle2() + .getInstruction(); + ConstantPoolGen constantPool = classGen.getConstantPool(); + if (!className.equals(nVOKESPECIAL.getText2(constantPool))) { + instructionHandle2 = instructionHandle; + } else if (!"".equals(nVOKESPECIAL.getText4(constantPool))) { + instructionHandle2 = instructionHandle; + } else if (!"()V".equals(nVOKESPECIAL.getText3(constantPool))) { + instructionHandle2 = instructionHandle; + } else { + int value = 0; + InstructionHandle instructionHandle3 = null; + InstructionHandle instructionHandle4; + instructionHandle2 = + instructionHandle4 = + instructionHandle + .getInstructionHandle2() + .getInstructionHandle2() + .getInstructionHandle2(); + while (true) { + label109: + if (instructionHandle2 != null) { + Instruction instruction; + if (!((instruction = instructionHandle4.getInstruction()) + instanceof ArithmeticInstruction) + && !(instruction instanceof ArrayInstruction) + && !(instruction instanceof ConversionInstruction) + && !(instruction instanceof ConstantPushInstruction) + && !(instruction instanceof FieldOrMethod) + && !(instruction instanceof LocalVariableInstruction) + && !(instruction instanceof PushInstruction) + && !(instruction instanceof PopInstruction) + && !(instruction instanceof NEW) + && !(instruction instanceof NEWARRAY) + && !(instruction instanceof NOP)) { + instructionHandle2 = instructionHandle3; + break; + } + if (!this.matchesInstructionTargeters(instructionHandle4.getTargeters())) { + instructionHandle2 = instructionHandle3; + break; + } + if (instructionHandle4.getInstruction() instanceof INVOKEVIRTUAL) { + INVOKEVIRTUAL nVOKEVIRTUAL = + (INVOKEVIRTUAL) instructionHandle4.getInstruction(); + if (className.equals(nVOKEVIRTUAL.getText2(constantPool)) + && "append".equals(nVOKEVIRTUAL.getText4(constantPool)) + && ("(Ljava/lang/String;)" + text) + .equals(nVOKEVIRTUAL.getText3(constantPool))) { + if (value == 1) { + instructionHandle2 = instructionHandle3 = instructionHandle4; + break; + } + break label109; + } + } + int value2 = instructionHandle4.getInstruction().produceStack(constantPool); + int value3 = instructionHandle4.getInstruction().consumeStack(constantPool); + if (value2 != -2) { + if (value3 == -2) { + instructionHandle2 = instructionHandle3; + break; + } + int value4; + if ((value4 = value - value3) < 0) { + instructionHandle2 = instructionHandle3; + break; + } + value = value4 + value2; + instructionHandle2 = + instructionHandle4 = instructionHandle4.getInstructionHandle2(); + continue; + } + } + instructionHandle2 = instructionHandle3; + break; + } + if (instructionHandle2 == null) { + instructionHandle2 = instructionHandle; + } else { + OptimizationStatistics.count31++; + instructionList.createInstructionHandle2( + instructionHandle.getInstructionHandle2().getInstructionHandle2(), + InstructionConstants.ICONST_0); + ((INVOKEVIRTUAL) instructionHandle3.getInstruction()) + .setIndex( + constantPool.addMethodref( + className, "insert", "(ILjava/lang/String;)" + text)); + instructionHandle2 = instructionHandle; + } + } + } + } + } + instructionHandle2 = instructionHandle = instructionHandle2.getInstructionHandle2(); + } + } + + public void processInstructionHandle( + InstructionTargeter[] instructionTargeters, + InstructionHandle instructionHandle, + InstructionHandle instructionHandle2) { + if (instructionTargeters != null) { + int value; + for (int value2 = value = 0; value2 < instructionTargeters.length; value2 = value) { + InstructionTargeter instructionTargeter = instructionTargeters[value]; + value++; + instructionTargeter.updateTarget(instructionHandle, instructionHandle2); + } + } + } + + public static int[] getCounts() { + int value = 0; + int value2 = 0; + int value3; + for (int value4 = value3 = 0; value4 < 32; value4 = ++value3) { + if (RandomUtils.calculateValue() < 0.5) { + value |= 1 << value3; + } else { + value2 |= 1 << value3; + } + } + return new int[] {value, value2}; + } + + public void processInstructionHandle2( + InstructionHandle instructionHandle, InstructionHandle instructionHandle2) { + if (instructionHandle2 != null) { + if (instructionHandle.getTargeters() != null) { + InstructionTargeter[] instructionTargeters; + int value = (instructionTargeters = instructionHandle.getTargeters()).length; + int value2; + for (int value3 = value2 = 0; value3 < value; value3 = ++value2) { + InstructionTargeter instructionTargeter; + if ((instructionTargeter = instructionTargeters[value2]) instanceof LocalVariableGen) { + instructionTargeter.updateTarget(instructionHandle, instructionHandle2); + } + } + } + } + } + + public void processInstructionList21( + ClassGen classGen, MethodGen methodGen, InstructionList instructionList) { + boolean matches; + instructionList.update(); + LocalVariableGen[] localVariableGens; + if ((localVariableGens = methodGen.getLocalVariables()) != null) { + int value = methodGen.getArgumentNames().length; + if (!methodGen.isEnabled11()) { + value++; + } + Type[] types; + int value2 = (types = methodGen.getArgumentTypes()).length; + int value3; + for (int value4 = value3 = 0; value4 < value2; value4 = ++value3) { + Type type; + if ((type = types[value3]) == Type.LONG || type == Type.DOUBLE) { + value++; + } + } + LocalVariableGen[] localVariableGens2 = localVariableGens; + int value5 = localVariableGens.length; + int value6; + for (int value7 = value6 = 0; value7 < value5; value7 = ++value6) { + LocalVariableGen localVariableGen; + if ((localVariableGen = localVariableGens2[value6]).getType() == Type.BOOLEAN + || localVariableGen.getType() == Type.BYTE + || localVariableGen.getType() == Type.SHORT + || localVariableGen.getType() == Type.CHAR) { + localVariableGen.setType(Type.INT); + } + } + int value8; + InstructionHandle[] instructionHandles = new InstructionHandle[value8 = methodGen.getCount()]; + InstructionHandle[] instructionHandles2 = new InstructionHandle[value8]; + boolean[] matchess = new boolean[value8]; + Hashtable hashtable = new Hashtable(); + InstructionHandle instructionHandle; + for (InstructionHandle instructionHandle2 = instructionHandle = instructionList.getStart(); + instructionHandle2 != null; + instructionHandle2 = instructionHandle = instructionHandle.getInstructionHandle2()) { + if (instructionHandle.getInstruction() instanceof LocalVariableInstruction) { + LocalVariableInstruction localVariableInstruction = + (LocalVariableInstruction) instructionHandle.getInstruction(); + int value9; + LocalVariableInstruction localVariableInstruction2; + if (instructionHandles[value9 = localVariableInstruction.getIndex()] == null) { + if (value9 < value) { + localVariableInstruction2 = localVariableInstruction; + instructionHandles[value9] = instructionList.getStart(); + instructionHandles2[value9] = instructionHandle; + } else { + instructionHandles[value9] = instructionHandles2[value9] = instructionHandle; + localVariableInstruction2 = localVariableInstruction; + } + } else { + instructionHandles2[value9] = instructionHandle; + localVariableInstruction2 = localVariableInstruction; + } + boolean matches2 = + localVariableInstruction2.produceStack(classGen.getConstantPool()) == 2 + || localVariableInstruction.consumeStack(classGen.getConstantPool()) == 2; + if (matches2 && value9 + 1 < value8) { + matchess[value9] = true; + if (instructionHandles[value9 + 1] == null) { + if (value9 + 1 < value) { + instructionHandles[value9 + 1] = instructionList.getStart(); + instructionHandles2[value9 + 1] = instructionHandle; + } else { + instructionHandles[value9 + 1] = + instructionHandles2[value9 + 1] = instructionHandle; + } + } else { + instructionHandles2[value9 + 1] = instructionHandle; + } + } + } else if (instructionHandle.getInstruction() instanceof RET) { + RET rET = (RET) instructionHandle.getInstruction(); + int value10; + if (instructionHandles[value10 = rET.getIndex()] == null) { + if (value10 < value) { + instructionHandles[value10] = instructionList.getStart(); + instructionHandles2[value10] = instructionHandle; + } else { + instructionHandles[value10] = instructionHandles2[value10] = instructionHandle; + } + } else { + instructionHandles2[value10] = instructionHandle; + } + } else if (instructionHandle.getInstruction() instanceof BranchInstruction) { + hashtable.put((BranchInstruction) instructionHandle.getInstruction(), instructionHandle); + } + } + InstructionHandle instructionHandle3; + for (InstructionHandle instructionHandle4 = instructionHandle3 = instructionList.getStart(); + instructionHandle4 != null; + instructionHandle4 = instructionHandle3 = instructionHandle3.getInstructionHandle2()) { + if (instructionHandle3.getInstructionHandle2() != null + && instructionHandle3.getInstruction() instanceof ALOAD + && instructionHandle3.getInstructionHandle2().getInstruction() instanceof ATHROW) { + int index = ((ALOAD) instructionHandle3.getInstruction()).getIndex(); + instructionHandles[index] = instructionList.getStart(); + instructionHandles2[index] = instructionList.getEnd(); + } + } + int value11; + for (int value12 = value11 = 0; value12 < value8; value12 = ++value11) { + if (instructionHandles[value11] != null) { + while (true) { + boolean matches3 = false; + InstructionHandle instructionHandle5; + InstructionHandle instructionHandle6 = instructionHandle5 = instructionHandles[value11]; + while (true) { + if (instructionHandle6 == null) { + matches = matches3; + break; + } + InstructionTargeter[] instructionTargeters; + if ((instructionTargeters = instructionHandle5.getTargeters()) != null) { + InstructionTargeter[] instructionTargeters2 = instructionTargeters; + int value13 = instructionTargeters.length; + int value14; + for (int value15 = value14 = 0; value15 < value13; value15 = ++value14) { + InstructionHandle instructionHandle7; + InstructionTargeter instructionTargeter; + if ((instructionTargeter = instructionTargeters2[value14]) + instanceof BranchInstruction + && (instructionHandle7 = + (InstructionHandle) hashtable.get(instructionTargeter)) + != null) { + if (instructionHandle7.getPosition() + < instructionHandles[value11].getPosition()) { + instructionHandles[value11] = instructionHandle7; + if (matchess[value11] && value11 + 1 < value8) { + instructionHandles[value11 + 1] = instructionHandle7; + } + matches3 = true; + } + if (instructionHandle7.getPosition() + > instructionHandles2[value11].getPosition()) { + instructionHandles2[value11] = instructionHandle7; + if (matchess[value11] && value11 + 1 < value8) { + instructionHandles2[value11 + 1] = instructionHandle7; + } + matches3 = true; + } + } + } + } + if (instructionHandle5 == instructionHandles2[value11]) { + matches = matches3; + break; + } + instructionHandle6 = instructionHandle5 = instructionHandle5.getInstructionHandle2(); + } + if (!matches) { + break; + } + } + } + } + int[] values = new int[value8]; + byte value16 = 1; + int value17 = 1; + for (int value18 = value17; value18 < value8; value18 = ++value17) { + int value19; + if (matchess[value17] + && values[value17] == 0 + && value17 + 1 < value8 + && values[value17 + 1] == 0 + && !matchess[value17 - 1]) { + for (int value20 = value19 = Math.max(value17 + 2, value); + value20 < value8; + value20 = ++value19) { + if (matchess[value19] + && values[value19] == 0 + && !matchess[value19 - 1] + && instructionHandles2[value17] != null + && instructionHandles[value19] != null + && instructionHandles2[value17].getPosition() + < instructionHandles[value19].getPosition() + && instructionHandles2[value17 + 1] != null + && instructionHandles2[value17 + 1].getPosition() + < instructionHandles[value19].getPosition()) { + instructionHandles2[value17] = instructionHandles2[value19]; + instructionHandles2[value17 + 1] = instructionHandles2[value19]; + values[value19] = value17; + OptimizationStatistics.count4 += 2; + } + } + } + } + int value21; + for (int value22 = value21 = value16; value22 < value8; value22 = ++value21) { + int value23; + if (!matchess[value21] && !matchess[value21 - 1] && values[value21] == 0) { + for (int value24 = value23 = Math.max(value21 + 1, value); + value24 < value8; + value24 = ++value23) { + if (!matchess[value23] + && !matchess[value23 - 1] + && values[value23] == 0 + && (instructionHandles2[value21] != null + && instructionHandles[value23] != null + && instructionHandles2[value21].getPosition() + < instructionHandles[value23].getPosition() + || instructionHandles2[value21] == null + && instructionHandles[value23] != null)) { + instructionHandles2[value21] = instructionHandles2[value23]; + values[value23] = value21; + OptimizationStatistics.count4++; + } + } + } + } + int value25; + for (int value26 = value25 = value16; value26 < value8; value26 = ++value25) { + int value27; + if ((matchess[value25] || matchess[value25 - 1]) && values[value25] == 0) { + for (int value28 = value27 = Math.max(value25 + 2, value); + value28 < value8; + value28 = ++value27) { + if (!matchess[value27] + && !matchess[value27 - 1] + && values[value27] == 0 + && instructionHandles2[value25] != null + && instructionHandles[value27] != null + && instructionHandles2[value25].getPosition() + < instructionHandles[value27].getPosition()) { + instructionHandles2[value25] = instructionHandles2[value27]; + values[value27] = value25; + OptimizationStatistics.count4++; + } + } + } + } + InstructionHandle instructionHandle8; + for (InstructionHandle instructionHandle9 = instructionHandle8 = instructionList.getStart(); + instructionHandle9 != null; + instructionHandle9 = instructionHandle8 = instructionHandle8.getInstructionHandle2()) { + if (instructionHandle8.getInstruction() instanceof LocalVariableInstruction) { + LocalVariableInstruction localVariableInstruction3 = + (LocalVariableInstruction) instructionHandle8.getInstruction(); + if (values[localVariableInstruction3.getIndex()] != 0) { + localVariableInstruction3.setIndex(values[localVariableInstruction3.getIndex()]); + } + } else if (instructionHandle8.getInstruction() instanceof RET) { + RET rET2 = (RET) instructionHandle8.getInstruction(); + if (values[rET2.getIndex()] != 0) { + rET2.setIndex(values[rET2.getIndex()]); + } + } + } + Arrays.fill(matchess, false); + InstructionHandle instructionHandle10; + for (InstructionHandle instructionHandle11 = instructionHandle10 = instructionList.getStart(); + instructionHandle11 != null; + instructionHandle11 = instructionHandle10 = instructionHandle10.getInstructionHandle2()) { + if (instructionHandle10.getInstruction() instanceof LocalVariableInstruction) { + LocalVariableInstruction localVariableInstruction4 = + (LocalVariableInstruction) instructionHandle10.getInstruction(); + int value29; + matchess[value29 = localVariableInstruction4.getIndex()] = true; + boolean matches4 = + localVariableInstruction4.produceStack(classGen.getConstantPool()) == 2 + || localVariableInstruction4.consumeStack(classGen.getConstantPool()) == 2; + if (matches4 && value29 + 1 < value8) { + matchess[value29 + 1] = true; + } + } else if (instructionHandle10.getInstruction() instanceof RET) { + RET rET3 = (RET) instructionHandle10.getInstruction(); + matchess[rET3.getIndex()] = true; + } + } + int value30; + for (int value31 = value30 = value; value31 < value8; value31 = value30) { + int value32 = value30; + int value33 = value30; + value30++; + values[value33] = value32; + } + int value34; + for (int value35 = value34 = value; value35 < value8; value35 = ++value34) { + int value36; + if (!matchess[value34]) { + for (int value37 = value36 = value34 + 1; value37 < value8; value37 = value36) { + int value38 = values[value36] - 1; + int value39 = value36; + value36++; + values[value39] = value38; + } + } + } + InstructionHandle instructionHandle12; + for (InstructionHandle instructionHandle13 = instructionHandle12 = instructionList.getStart(); + instructionHandle13 != null; + instructionHandle13 = instructionHandle12 = instructionHandle12.getInstructionHandle2()) { + if (instructionHandle12.getInstruction() instanceof LocalVariableInstruction) { + LocalVariableInstruction localVariableInstruction5; + if ((localVariableInstruction5 = + (LocalVariableInstruction) instructionHandle12.getInstruction()) + .getIndex() + >= value) { + localVariableInstruction5.setIndex(values[localVariableInstruction5.getIndex()]); + } + } else { + RET rET4; + if (instructionHandle12.getInstruction() instanceof RET + && (rET4 = (RET) instructionHandle12.getInstruction()).getIndex() >= value) { + rET4.setIndex(values[rET4.getIndex()]); + } + } + } + LocalVariableGen[] localVariableGens3 = localVariableGens; + int value40 = localVariableGens.length; + int value41; + for (int value42 = value41 = 0; value42 < value40; value42 = ++value41) { + LocalVariableGen localVariableGen2; + if ((localVariableGen2 = localVariableGens3[value41]).getIndex() < value) { + localVariableGen2.processInstructionHandle2(instructionList.getStart()); + localVariableGen2.processInstructionHandle(instructionList.getEnd()); + } else { + methodGen.removeLocalVariable(localVariableGen2); + } + } + } + } + + public boolean matchesInstruction(Instruction instruction) { + return instruction instanceof ConstantPushInstruction + || instruction instanceof ACONST_NULL + || instruction instanceof LDC + || instruction instanceof LDC2_W; + } + + public void processInstructionList22( + ClassGen classGen, MethodGen methodGen, InstructionList instructionList) {} + + public void processInstructionList23( + ClassGen classGen, MethodGen methodGen, InstructionList instructionList) { + InstructionHandle instructionHandle; + LocalVariableGen[] localVariableGens; + if ((localVariableGens = methodGen.getLocalVariables()) != null) { + if (localVariableGens.length != 0) { + int value; + if ((value = methodGen.getCount()) >= 2) { + int[] values = new int[value]; + boolean[] matchess = new boolean[value]; + Type[] types = new Type[value]; + int value2 = 0; + if (!methodGen.isEnabled11()) { + types[0] = Type.OBJECT; + value2 = 1; + } + int value3 = methodGen.getArgumentNames().length; + if (!methodGen.isEnabled11()) { + value3++; + } + Type[] types2; + int value4 = (types2 = methodGen.getArgumentTypes()).length; + int value5; + for (int value6 = value5 = 0; value6 < value4; value6 = ++value5) { + Type type = types2[value5]; + Type type2; + Type type3 = type2 = type; + int value7 = value2; + value2++; + types[value7] = type2; + if (type3 == Type.LONG || type == Type.DOUBLE) { + int value8 = value2 - 1; + boolean matches = matchess[value2] = true; + value3++; + matchess[value8] = matches; + int value9 = value2; + value2++; + types[value9] = type; + } + } + InstructionHandle instructionHandle2; + for (InstructionHandle instructionHandle3 = + instructionHandle2 = instructionList.getStart(); + instructionHandle3 != null; + instructionHandle3 = + instructionHandle2 = instructionHandle2.getInstructionHandle2()) { + if (instructionHandle2.getInstruction() instanceof LoadInstruction + || instructionHandle2.getInstruction() instanceof StoreInstruction) { + LocalVariableInstruction localVariableInstruction = + (LocalVariableInstruction) instructionHandle2.getInstruction(); + int value10; + values[value10 = localVariableInstruction.getIndex()]++; + if (types[value10] == null) { + types[value10] = localVariableInstruction.getType(classGen.getConstantPool()); + } + if ((localVariableInstruction.produceStack(classGen.getConstantPool()) == 2 + || localVariableInstruction.consumeStack(classGen.getConstantPool()) == 2) + && value10 + 1 < value) { + matchess[value10] = true; + matchess[value10 + 1] = true; + } + } + } + int value11; + for (int value12 = value11 = 0; value12 < values.length; value12 = value11) { + int value13 = values[value11] << 16 | value11; + int value14 = value11; + value11++; + values[value14] = value13; + } + Arrays.sort(values); + byte value15 = 0; + int value16; + for (int value17 = value16 = 0; value17 < value3 && value15 == 0; value17 = ++value16) { + int value18; + if (types[value16] != null) { + for (int value19 = value18 = value - 1; value19 >= 0; value19 = --value18) { + int value20; + if ((value20 = values[value18] & 65535) > value16 + && !matchess[value16] + && !matchess[value20] + && types[value20] != null) { + OptimizationStatistics.count7++; + InstructionHandle instructionHandle4; + InstructionHandle instructionHandle5 = + instructionHandle4 = instructionList.getStart(); + while (instructionHandle5 != null) { + label95: + { + if (instructionHandle4.getInstruction() instanceof LocalVariableInstruction) { + LocalVariableInstruction localVariableInstruction2; + if ((localVariableInstruction2 = + (LocalVariableInstruction) instructionHandle4.getInstruction()) + .getIndex() + == value16) { + localVariableInstruction2.setIndex(value20); + } else if (localVariableInstruction2.getIndex() == value20) { + localVariableInstruction2.setIndex(value16); + } + } else if (instructionHandle4.getInstruction() instanceof RET) { + RET rET; + if ((rET = (RET) instructionHandle4.getInstruction()).getIndex() + == value16) { + instructionHandle = instructionHandle4; + rET.setIndex(value20); + break label95; + } + if (rET.getIndex() == value20) { + rET.setIndex(value16); + } + } + instructionHandle = instructionHandle4; + } + instructionHandle5 = + instructionHandle4 = instructionHandle.getInstructionHandle2(); + } + InstructionHandle start = instructionList.getStart(); + if (value20 < value3) { + instructionList.createInstructionHandle( + instructionList.createInstructionHandle( + instructionList.createInstructionHandle( + instructionList.createInstructionHandle( + start, + InstructionFactory.createLocalVariableInstruction( + types[value16], value20)), + InstructionFactory.createLocalVariableInstruction( + types[value20], value16)), + InstructionFactory.createLocalVariableInstruction2( + types[value20], value20)), + InstructionFactory.createLocalVariableInstruction2( + types[value16], value16)); + } else { + instructionList.createInstructionHandle( + instructionList.createInstructionHandle( + start, + InstructionFactory.createLocalVariableInstruction( + types[value16], value20)), + InstructionFactory.createLocalVariableInstruction2( + types[value16], value16)); + } + value15 = 1; + break; + } + } + } + } + if (value15 != 0) {} + } + } + } + } + + public boolean matchesInstructionTargeters(InstructionTargeter[] instructionTargeters) { + if (instructionTargeters == null) { + return true; + } + int value; + for (int value2 = value = 0; value2 < instructionTargeters.length; value2 = ++value) { + InstructionTargeter instructionTargeter; + if (!((instructionTargeter = instructionTargeters[value]) instanceof LineNumberGen) + && !(instructionTargeter instanceof LocalVariableGen)) { + return false; + } + } + return true; + } + + public void processInstructionList24( + ClassGen classGen, MethodGen methodGen, InstructionList instructionList) { + instructionList.update(); + InstructionHandle instructionHandle; + InstructionHandle instructionHandle2 = instructionHandle = instructionList.getStart(); + while (instructionHandle2 != null) { + label72: + { + if (instructionHandle.getInstruction() instanceof IfInstruction) { + byte value = 1; + byte value2 = 1; + InstructionHandle instructionHandle3 = instructionHandle; + InstructionHandle instructionHandle4; + if ((instructionHandle4 = + ((IfInstruction) instructionHandle.getInstruction()).getTarget()) + .getPosition() + >= instructionHandle3.getPosition()) { + value = 0; + } + if (instructionHandle4.getPosition() <= instructionHandle3.getPosition()) { + value2 = 0; + } + if (value == 0 && value2 == 0) { + instructionHandle2 = instructionHandle; + break label72; + } + InstructionHandle instructionHandle5; + if ((instructionHandle5 = instructionHandle4.getInstructionHandle()) == null) { + instructionHandle2 = instructionHandle; + break label72; + } + if (!(instructionHandle5.getInstruction() instanceof GotoInstruction)) { + instructionHandle2 = instructionHandle; + break label72; + } + GotoInstruction gotoInstruction; + InstructionHandle target = + (gotoInstruction = (GotoInstruction) instructionHandle5.getInstruction()).getTarget(); + if (value != 0) { + if (target.getPosition() >= instructionHandle3.getPosition()) { + instructionHandle2 = instructionHandle; + break label72; + } + if (instructionHandle4.getPosition() >= target.getPosition()) { + instructionHandle2 = instructionHandle; + break label72; + } + } else if (value2 != 0 && target.getPosition() >= instructionHandle3.getPosition()) { + instructionHandle2 = instructionHandle; + break label72; + } + if (target.getInstruction() instanceof BranchInstruction) { + instructionHandle2 = instructionHandle; + break label72; + } + if (target.getInstruction() instanceof NEW) { + instructionHandle2 = instructionHandle; + break label72; + } + if (target.getInstruction() instanceof NEWARRAY) { + instructionHandle2 = instructionHandle; + break label72; + } + if (target.getInstruction() instanceof ANEWARRAY) { + instructionHandle2 = instructionHandle; + break label72; + } + if (!this.matchesInstructionTargeters( + instructionHandle4.getInstructionHandle().getTargeters())) { + instructionHandle2 = instructionHandle; + break label72; + } + OptimizationStatistics.count26++; + gotoInstruction.setTarget(target.getInstructionHandle2()); + instructionList.createInstructionHandle( + instructionHandle4.getInstructionHandle(), target.getInstruction()); + } + instructionHandle2 = instructionHandle; + } + instructionHandle2 = instructionHandle = instructionHandle2.getInstructionHandle2(); + } + } + + public void processInstructionList25( + ClassGen classGen, MethodGen methodGen, InstructionList instructionList) { + InstructionList instructionList2; + InstructionHandle instructionHandle; + InstructionHandle instructionHandle2 = instructionHandle = instructionList.getStart(); + while (instructionHandle2 != null) { + if (!(instructionHandle.getInstruction() instanceof StoreInstruction)) { + instructionHandle2 = instructionHandle; + } else if (instructionHandle.getInstructionHandle2() == null) { + instructionHandle2 = instructionHandle; + } else if (!(instructionHandle.getInstructionHandle2().getInstruction() + instanceof LoadInstruction)) { + instructionHandle2 = instructionHandle; + } else { + InstructionHandle instructionHandle3 = instructionHandle; + InstructionHandle instructionHandle22 = instructionHandle.getInstructionHandle2(); + StoreInstruction storeInstruction = (StoreInstruction) instructionHandle3.getInstruction(); + LoadInstruction loadInstruction = (LoadInstruction) instructionHandle22.getInstruction(); + if (storeInstruction.getIndex() != loadInstruction.getIndex()) { + instructionHandle2 = instructionHandle; + } else if (!this.matchesInstructionTargeters(instructionHandle22.getTargeters())) { + instructionHandle2 = instructionHandle; + } else if (!this.matchesInstructionTargeters(instructionHandle3.getTargeters())) { + instructionHandle2 = instructionHandle; + } else { + InstructionHandle instructionHandle4; + if ((instructionHandle4 = instructionHandle22.getInstructionHandle2()) == null) { + instructionHandle2 = instructionHandle; + } else { + label78: + { + InstructionHandle instructionHandle5; + instructionHandle5 = instructionHandle4; + label55: + if (this.matchesInstructionHandle( + instructionList, instructionHandle3, instructionHandle22)) { + OptimizationStatistics.count3++; + this.processInstructionHandle(instructionHandle22, instructionHandle4); + this.processInstructionHandle(instructionHandle3, instructionHandle4); + this.processInstructionHandle2(instructionHandle22, instructionHandle4); + this.processInstructionHandle2(instructionHandle3, instructionHandle4); + label52: + { + try { + instructionList.processInstructionHandle2(instructionHandle3); + } catch (TargetLostException targetLostException) { + { + instructionList2 = instructionList; + break label52; + } + } + instructionList2 = instructionList; + } + try { + instructionList2.processInstructionHandle2(instructionHandle22); + } catch (TargetLostException targetLostException2) { + break label55; + } + instructionHandle2 = instructionHandle5; + break label78; + } + instructionHandle2 = instructionHandle5; + } + } + } + } + instructionHandle2 = instructionHandle = instructionHandle2.getInstructionHandle2(); + } + } + + public void processInstructionList26( + ClassGen classGen, MethodGen methodGen, InstructionList instructionList) {} + + public void processInstructionList27( + ClassGen classGen, MethodGen methodGen, InstructionList instructionList) { + int value; + InstructionHandle instructionHandle; + InstructionHandle instructionHandle2 = instructionHandle = instructionList.getStart(); + while (instructionHandle2 != null) { + if (!(instructionHandle.getInstruction() instanceof LoadInstruction)) { + instructionHandle2 = instructionHandle; + } else if (instructionHandle.getInstructionHandle2() == null) { + instructionHandle2 = instructionHandle; + } else if (!(instructionHandle.getInstructionHandle2().getInstruction() + instanceof LoadInstruction)) { + instructionHandle2 = instructionHandle; + } else { + InstructionHandle instructionHandle3 = instructionHandle; + LoadInstruction loadInstruction = (LoadInstruction) instructionHandle.getInstruction(); + int index = loadInstruction.getIndex(); + int value2 = 1; + InstructionHandle instructionHandle4; + instructionHandle2 = instructionHandle4 = instructionHandle3.getInstructionHandle2(); + while (instructionHandle2 != null + && instructionHandle4.getInstruction() instanceof LoadInstruction + && ((LoadInstruction) instructionHandle4.getInstruction()).getIndex() == index) { + InstructionHandle instructionHandle5; + InstructionHandle instructionHandle6 = + instructionHandle5 = instructionHandle4.getInstructionHandle2(); + value2++; + instructionHandle2 = instructionHandle6; + instructionHandle4 = instructionHandle5; + } + if (value2 == 1) { + instructionHandle2 = instructionHandle; + } else if (instructionHandle4 == null) { + instructionHandle2 = instructionHandle; + } else { + byte value3 = 1; + InstructionHandle instructionHandle22 = instructionHandle3.getInstructionHandle2(); + int value4; + int value5 = value4 = 1; + while (true) { + if (value5 >= value2) { + value = value3; + break; + } + if (!this.matchesInstructionTargeters(instructionHandle22.getTargeters())) { + value = 0; + break; + } + InstructionHandle instructionHandle7 = instructionHandle22; + value4++; + instructionHandle22 = instructionHandle7.getInstructionHandle2(); + value5 = value4; + } + if (value == 0) { + instructionHandle2 = instructionHandle; + } else { + OptimizationStatistics.count10++; + if (value2 > 2) { + OptimizationStatistics.count23++; + } + InstructionHandle instructionHandle23 = instructionHandle3.getInstructionHandle2(); + int value6; + for (int value7 = value6 = 1; value7 < value2; value7 = value6) { + this.processInstructionHandle2(instructionHandle23, instructionHandle3); + label111: + { + try { + instructionList.processInstructionHandle2(instructionHandle23); + } catch (TargetLostException targetLostException) { + instructionHandle2 = instructionHandle3; + break label111; + } + instructionHandle2 = instructionHandle3; + } + InstructionHandle instructionHandle24 = instructionHandle2.getInstructionHandle2(); + value6++; + instructionHandle23 = instructionHandle24; + } + if (!(loadInstruction instanceof ALOAD) + && !(loadInstruction instanceof FLOAD) + && !(loadInstruction instanceof ILOAD)) { + int value8; + if (loadInstruction instanceof DLOAD || loadInstruction instanceof LLOAD) { + for (int value9 = value8 = 1; value9 < value2; value9 = value8) { + value8++; + instructionList.createInstructionHandle2( + instructionHandle3, InstructionConstants.DUP2); + } + } + } else { + int value10 = 1; + label98: + while (true) { + int value11 = value10; + while (true) { + if (value11 >= value2) { + break label98; + } + if (value2 - value10 > 2) { + value10 += 2; + instructionList.createInstructionHandle2( + instructionHandle3, InstructionConstants.DUP2); + } + if (value2 - value10 == 2) { + value10++; + instructionList.createInstructionHandle2( + instructionHandle3, InstructionConstants.DUP_X1); + } + if (value2 - value10 != 1) { + break; + } + value10++; + instructionList.createInstructionHandle2( + instructionHandle3, InstructionConstants.DUP); + value11 = value10; + } + } + } + instructionHandle2 = instructionHandle; + } + } + } + instructionHandle2 = instructionHandle = instructionHandle2.getInstructionHandle2(); + } + } +} diff --git a/src/main/java/com/allatori/optimizer/OptimizationStatistics.java b/src/main/java/com/allatori/optimizer/OptimizationStatistics.java new file mode 100644 index 0000000..f80ac53 --- /dev/null +++ b/src/main/java/com/allatori/optimizer/OptimizationStatistics.java @@ -0,0 +1,70 @@ +package com.allatori.optimizer; + +public class OptimizationStatistics { + + public static int count; + + public static int count2; + + public static int count3; + + public static int count4; + + public static int count5; + + public static int count6; + + public static int count7; + + public static int count8; + + public static int count9; + + public static int count10; + + public static int count11; + + public static int count12; + + public static int count13; + + public static int count14; + + public static int count15; + + public static int count16; + + public static int count17; + + public static int count18; + + public static int count19; + + public static int count20; + + public static int count21; + + public static int count22; + + public static int count23; + + public static int count24; + + public static int count25; + + public static int count26; + + public static int count27; + + public static int count28; + + public static int count29; + + public static int count30; + + public static int count31; + + public static int count32; + + public static int count33; +} diff --git a/src/main/java/com/allatori/stacktrace/MappingConstructorToken.java b/src/main/java/com/allatori/stacktrace/MappingConstructorToken.java new file mode 100644 index 0000000..7fc1193 --- /dev/null +++ b/src/main/java/com/allatori/stacktrace/MappingConstructorToken.java @@ -0,0 +1,3 @@ +package com.allatori.stacktrace; + +public class MappingConstructorToken {} diff --git a/src/main/java/com/allatori/stacktrace/MappingXmlHandler.java b/src/main/java/com/allatori/stacktrace/MappingXmlHandler.java new file mode 100644 index 0000000..14f447e --- /dev/null +++ b/src/main/java/com/allatori/stacktrace/MappingXmlHandler.java @@ -0,0 +1,92 @@ +package com.allatori.stacktrace; + +import com.allatori.util.LookupTable; +import java.util.Vector; +import org.xml.sax.Attributes; +import org.xml.sax.helpers.DefaultHandler; + +public class MappingXmlHandler extends DefaultHandler { + + public StackTraceMappings stackTraceMappings; + + public String text; + + public String text2; + + public String text3; + + public String text4; + + public String text5; + + public String text6; + + public String text7; + + public String text8; + + public String text9; + + public String text10; + + public String text11; + + public String text12; + + public String text13; + + public MappingXmlHandler(StackTraceMappings stackTraceMappings2) { + super(); + this.text5 = "old"; + this.text8 = "new"; + this.text = "class"; + this.text9 = "method"; + this.text3 = "source"; + this.text11 = "line"; + this.text10 = "l"; + this.text2 = ""; + this.text6 = ""; + this.text7 = "s"; + this.text13 = "e"; + this.stackTraceMappings = stackTraceMappings2; + stackTraceMappings2.lookupTable2 = new LookupTable(); + stackTraceMappings2.lookupTable = new LookupTable(); + stackTraceMappings2.values = new Vector(); + } + + @Override + public void startElement(String text14, String text15, String text16, Attributes attributes) { + if (this.text.equals(text16)) { + String value = attributes.getValue(this.text5); + String value2 = attributes.getValue(this.text8); + this.stackTraceMappings.lookupTable2.processText(value2, value); + this.text4 = value + "."; + this.text12 = "" + value2 + "."; + this.stackTraceMappings.processText( + "" + this.text12 + this.text2, "" + this.text4 + this.text2); + this.stackTraceMappings.processText( + "" + this.text12 + this.text6, "" + this.text4 + this.text6); + } else if (this.text9.equals(text16)) { + String value3 = attributes.getValue(this.text5); + String value4 = attributes.getValue(this.text8); + String text17 = value3.substring(0, value3.indexOf(40)); + if (attributes.getValue(this.text7) != null && attributes.getValue(this.text13) != null) { + int value5 = Integer.valueOf(attributes.getValue(this.text7)); + int value6 = Integer.valueOf(attributes.getValue(this.text13)); + this.stackTraceMappings.processCount( + "" + this.text12 + value4, "" + this.text4 + text17, value5, value6); + } else { + this.stackTraceMappings.processText("" + this.text12 + value4, "" + this.text4 + text17); + } + } else if (this.text3.equals(text16)) { + String value7 = attributes.getValue(this.text5); + String value8 = attributes.getValue(this.text8); + this.stackTraceMappings.lookupTable.processText(value8, value7); + } else { + if (this.text11.equals(text16)) { + Integer value9 = Integer.valueOf(attributes.getValue(this.text10)); + this.stackTraceMappings.values.add(value9); + } + } + } +} diff --git a/src/main/java/com/allatori/stacktrace/MappingXmlReader.java b/src/main/java/com/allatori/stacktrace/MappingXmlReader.java new file mode 100644 index 0000000..cdc90d2 --- /dev/null +++ b/src/main/java/com/allatori/stacktrace/MappingXmlReader.java @@ -0,0 +1,22 @@ +package com.allatori.stacktrace; + +import java.io.IOException; +import java.io.Reader; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; + +public class MappingXmlReader { + + public static StackTraceMappings createStackTraceMappings(Reader reader) + throws ParserConfigurationException, SAXException, IOException { + XMLReader xMLReader = SAXParserFactory.newInstance().newSAXParser().getXMLReader(); + StackTraceMappings stackTraceMappings; + StackTraceMappings stackTraceMappings2 = stackTraceMappings = new StackTraceMappings(); + xMLReader.setContentHandler(new MappingXmlHandler(stackTraceMappings)); + xMLReader.parse(new InputSource(reader)); + return stackTraceMappings2; + } +} diff --git a/src/main/java/com/allatori/stacktrace/StackTraceMappingEntry.java b/src/main/java/com/allatori/stacktrace/StackTraceMappingEntry.java new file mode 100644 index 0000000..d6b3abb --- /dev/null +++ b/src/main/java/com/allatori/stacktrace/StackTraceMappingEntry.java @@ -0,0 +1,34 @@ +package com.allatori.stacktrace; + +public class StackTraceMappingEntry { + + public int count; + + public int count2; + + public String text; + + public StackTraceMappingEntry( + String text, int value, int value2, MappingConstructorToken mappingConstructorToken) { + this(text, value, value2); + } + + public StackTraceMappingEntry(String text, int count2, int count) { + super(); + this.text = text; + this.count2 = count2; + this.count = count; + } + + public static int calculateCount(StackTraceMappingEntry stackTraceMappingEntry) { + return stackTraceMappingEntry.count2; + } + + public static String getText(StackTraceMappingEntry stackTraceMappingEntry) { + return stackTraceMappingEntry.text; + } + + public static int calculateCount2(StackTraceMappingEntry stackTraceMappingEntry) { + return stackTraceMappingEntry.count; + } +} diff --git a/src/main/java/com/allatori/stacktrace/StackTraceMappings.java b/src/main/java/com/allatori/stacktrace/StackTraceMappings.java new file mode 100644 index 0000000..3a43f89 --- /dev/null +++ b/src/main/java/com/allatori/stacktrace/StackTraceMappings.java @@ -0,0 +1,53 @@ +package com.allatori.stacktrace; + +import com.allatori.util.LookupTable; +import java.util.Hashtable; +import java.util.Vector; + +public class StackTraceMappings { + + public Vector values; + + public LookupTable lookupTable; + + public LookupTable lookupTable2; + + public Hashtable entries = new Hashtable(); + + public boolean matchesText(String text) { + return this.entries.containsKey(text); + } + + public void processText(String text, String text2) { + this.processCount(text, text2, -1, -1); + } + + public void processCount(String text, String text2, int value, int value2) { + if (!this.entries.containsKey(text)) { + this.entries.put(text, new Vector()); + } + ((Vector) this.entries.get(text)).add(new StackTraceMappingEntry(text2, value, value2, null)); + } + + public String getText(String text, int value) { + Vector vector; + for (StackTraceMappingEntry stackTraceMappingEntry : + ((Iterable) + ((Iterable) (vector = (Vector) this.entries.get(text))))) { + if (value >= StackTraceMappingEntry.calculateCount(stackTraceMappingEntry) + && value <= StackTraceMappingEntry.calculateCount2(stackTraceMappingEntry)) { + return StackTraceMappingEntry.getText(stackTraceMappingEntry); + } + } + return vector.size() > 0 + ? StackTraceMappingEntry.getText((StackTraceMappingEntry) vector.get(0)) + : null; + } + + public String getText(String text) { + Vector vector; + return (vector = (Vector) this.entries.get(text)).size() > 0 + ? StackTraceMappingEntry.getText((StackTraceMappingEntry) vector.get(0)) + : null; + } +} diff --git a/src/main/java/com/allatori/stacktrace/StackTraceRestorer.java b/src/main/java/com/allatori/stacktrace/StackTraceRestorer.java new file mode 100644 index 0000000..ba9ab4f --- /dev/null +++ b/src/main/java/com/allatori/stacktrace/StackTraceRestorer.java @@ -0,0 +1,308 @@ +package com.allatori.stacktrace; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class StackTraceRestorer { + + public static String getText(String text, StackTraceMappings stackTraceMappings) { + String text2 = text; + Matcher matcher2 = Pattern.compile("L(.*?);").matcher(text2); + while (matcher2.find()) { + String text3; + String text4 = (text3 = matcher2.group(1)).replace('/', '.'); + if (stackTraceMappings.lookupTable2.matchesText(text4)) { + text2 = + text2.replace(text3, stackTraceMappings.lookupTable2.getText(text4).replace('.', '/')); + } + } + return text2; + } + + public static void processPrintWriter( + BufferedReader bufferedReader, StackTraceMappings stackTraceMappings, PrintWriter printWriter) + throws IOException { + PrintWriter printWriter2; + PrintWriter printWriter3; + Pattern pattern = Pattern.compile("(.*(?:at|Frame)\\s+)(.*)\\((.*)\\)(.*)"); + Pattern pattern2 = Pattern.compile("(.*syslog:\\s+)(.*?)\\((.*)\\)(.*)"); + Pattern pattern3 = Pattern.compile("(\\s*)(.*?)\\((.*)\\)(.*)"); + Pattern pattern4 = + Pattern.compile( + "(.*?\\s+)((?:\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*\\.)+\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*):(\\d+)(\\s+.*)"); + Pattern pattern5 = Pattern.compile("(.*lock.*a\\s+)(.*?)(\\).*)"); + String text = null; + String text2 = null; + String text3 = null; + String text4 = null; + BufferedReader bufferedReader2 = bufferedReader; + String text5; + while ((text5 = bufferedReader2.readLine()) != null) { + byte value = 0; + Matcher matcher2; + if ((matcher2 = pattern.matcher(text5)).matches()) { + value = 1; + text = matcher2.group(1); + if ((text2 = matcher2.group(2)).indexOf(40) > 0) { + text2 = text2.substring(0, text2.indexOf(40)); + } + text3 = matcher2.group(3); + text4 = matcher2.group(4); + } + Matcher matcher3; + if (value == 0 && (matcher3 = pattern2.matcher(text5)).matches()) { + value = 1; + text = matcher3.group(1); + text2 = matcher3.group(2); + text3 = matcher3.group(3); + text4 = matcher3.group(4); + } + Matcher matcher4; + if (value == 0 && (matcher4 = pattern3.matcher(text5)).matches()) { + value = 1; + text = matcher4.group(1); + text2 = matcher4.group(2); + text3 = matcher4.group(3); + text4 = matcher4.group(4); + } + Matcher matcher5; + if (value == 0 && (matcher5 = pattern4.matcher(text5)).matches()) { + text = matcher5.group(1); + String text6 = matcher5.group(2); + text3 = matcher5.group(3); + text4 = matcher5.group(4); + if (stackTraceMappings.lookupTable2.matchesText(text6)) { + label96: + { + try { + text5 = + "" + + text + + stackTraceMappings.lookupTable2.getText(text6) + + ":" + + stackTraceMappings.values.indexOf(Integer.valueOf(text3)) + + text4; + } catch (Exception exception) { + printWriter3 = printWriter; + break label96; + } + printWriter3 = printWriter; + } + printWriter3.println(text5); + bufferedReader2 = bufferedReader; + continue; + } + } + label89: + { + if (value != 0) { + if (stackTraceMappings.matchesText(text2)) { + byte value2 = 0; + if (text3.startsWith("(Compiled Method)")) { + value2 = 1; + text3 = text3.substring("(Compiled Method)".length()); + } + int value3 = -1; + StackTraceMappings stackTraceMappings2; + if (text3.indexOf(58) >= 0) { + String text7 = text3.substring(0, text3.indexOf(58)); + String text8 = text3.substring(text3.indexOf(58) + 1); + if (stackTraceMappings.lookupTable.matchesText(text7)) { + text7 = stackTraceMappings.lookupTable.getText(text7); + } + try { + if ((value3 = stackTraceMappings.values.indexOf(Integer.valueOf(text8))) >= 0) { + text8 = "" + value3; + } + } catch (NumberFormatException numberFormatException) { + } + text3 = "" + text7 + ":" + text8; + stackTraceMappings2 = stackTraceMappings; + } else { + if (stackTraceMappings.lookupTable.matchesText(text3)) { + text3 = stackTraceMappings.lookupTable.getText(text3); + } + stackTraceMappings2 = stackTraceMappings; + } + String text9; + if ((text9 = stackTraceMappings2.getText(text2, value3)) == null) { + text9 = stackTraceMappings.getText(text2); + } + text5 = + "" + + text + + text9 + + (value2 != 0 ? "(Compiled Method)" : "") + + "(" + + text3 + + ")" + + text4; + printWriter2 = printWriter; + break label89; + } + } else { + Matcher matcher6; + if ((matcher6 = pattern5.matcher(text5)).matches() + && stackTraceMappings.lookupTable2.matchesText(matcher6.group(2))) { + text5 = + "" + + matcher6.group(1) + + stackTraceMappings.lookupTable2.getText(matcher6.group(2)) + + matcher6.group(3); + } + } + printWriter2 = printWriter; + } + printWriter2.println(text5); + bufferedReader2 = bufferedReader; + } + } + + public static void processPrintWriter2( + BufferedReader bufferedReader, StackTraceMappings stackTraceMappings, PrintWriter printWriter) + throws IOException { + StackTraceMappings stackTraceMappings2; + int value; + StringBuilder stringBuilder = new StringBuilder(); + BufferedReader bufferedReader2 = bufferedReader; + String text; + while ((text = bufferedReader2.readLine()) != null) { + int value2 = 0; + int size = text.length(); + stringBuilder.setLength(0); + do { + int value3 = -1; + int value4 = -1; + int value5 = -1; + int value6 = -1; + int value7 = value2; + int value8 = value2; + while (value8 < size && !Character.isJavaIdentifierStart(text.charAt(value2))) { + value8 = ++value2; + } + int value9 = value2; + int value10 = value2; + while (value10 < size + && (Character.isJavaIdentifierPart(text.charAt(value2)) + || text.charAt(value2) == '.' + || text.charAt(value2) == '-' + || text.charAt(value2) == '<' + || text.charAt(value2) == '>')) { + value10 = ++value2; + } + int value11 = value2; + int value12 = value2; + while (value12 < size && text.charAt(value2) == ' ') { + value12 = ++value2; + } + label210: + { + if (value2 < size && text.charAt(value2) == '(') { + value6 = ++value2; + int value13 = value2; + while (value13 < size && Character.isLetter(text.charAt(value2))) { + value13 = ++value2; + } + value5 = value2; + if (value2 < size && text.charAt(value2) == ':') { + value4 = ++value2; + int value14 = value2; + while (value14 < size && Character.isDigit(text.charAt(value2))) { + value14 = ++value2; + } + value3 = value2; + value = value11; + break label210; + } + } else if (value2 < size && text.charAt(value2) == ':') { + value4 = ++value2; + int value15 = value2; + while (value15 < size && Character.isDigit(text.charAt(value2))) { + value15 = ++value2; + } + value3 = value2; + } + value = value11; + } + if (value <= value9) { + stringBuilder.append(text.substring(value7, value2)); + } else { + String text2 = text.substring(value9, value11); + if (stackTraceMappings.matchesText(text2)) { + stringBuilder.append(text.substring(value7, value9)); + int value16; + if (value3 > value4) { + String text3 = text.substring(value4, value3); + int value17 = -1; + label174: + { + try { + value17 = stackTraceMappings.values.indexOf(Integer.valueOf(text3)); + } catch (NumberFormatException numberFormatException) { + stackTraceMappings2 = stackTraceMappings; + break label174; + } + stackTraceMappings2 = stackTraceMappings; + } + String text4; + if ((text4 = stackTraceMappings2.getText(text2, value17)) == null) { + text4 = stackTraceMappings.getText(text2); + } + stringBuilder.append(text4); + value16 = value5; + } else { + stringBuilder.append(stackTraceMappings.getText(text2)); + value16 = value5; + } + if (value16 > value6) { + String text5 = text.substring(value6, value5); + stringBuilder.append(text.substring(value11, value6)); + if (stackTraceMappings.lookupTable.matchesText(text5)) { + text5 = stackTraceMappings.lookupTable.getText(text5); + } + stringBuilder.append(text5); + if (value3 <= value4) { + stringBuilder.append(text.substring(value5, value2)); + } + } + if (value3 > value4) { + String text6 = text.substring(value4, value3); + try { + int value18; + if ((value18 = stackTraceMappings.values.indexOf(Integer.valueOf(text6))) >= 0) { + text6 = "" + value18; + } + } catch (NumberFormatException numberFormatException2) { + } + StringBuilder stringBuilder2; + if (value5 > value6) { + stringBuilder2 = stringBuilder; + stringBuilder.append(text.substring(value5, value4)); + } else { + stringBuilder2 = stringBuilder; + stringBuilder.append(text.substring(value11, value4)); + } + stringBuilder2.append(text6); + stringBuilder.append(text.substring(value3, value2)); + } + if (value5 <= value6 && value3 <= value4) { + stringBuilder.append(text.substring(value11, value2)); + } + } else if ((text2.indexOf(46) > 0 || text2.length() > 3) + && stackTraceMappings.lookupTable2.matchesText(text2)) { + stringBuilder.append(text.substring(value7, value9)); + stringBuilder.append(stackTraceMappings.lookupTable2.getText(text2)); + stringBuilder.append(text.substring(value11, value2)); + } else { + stringBuilder.append(text.substring(value7, value2)); + } + } + } while (value2 < size); + bufferedReader2 = bufferedReader; + printWriter.println(getText(stringBuilder.toString(), stackTraceMappings)); + } + } +} diff --git a/src/main/java/com/allatori/transform/ClassConstantPoolTransformer.java b/src/main/java/com/allatori/transform/ClassConstantPoolTransformer.java new file mode 100644 index 0000000..e3f8d78 --- /dev/null +++ b/src/main/java/com/allatori/transform/ClassConstantPoolTransformer.java @@ -0,0 +1,125 @@ +package com.allatori.transform; + +import com.allatori.bytecode.ConstantPoolEditor; +import com.allatori.bytecode.MethodFactory; +import com.allatori.crypto.CustomStringEncryption; +import com.allatori.lib.bcel.classfile.Constant; +import com.allatori.lib.bcel.classfile.ConstantString; +import com.allatori.lib.bcel.classfile.ConstantUtf8; +import com.allatori.lib.bcel.classfile.Method; +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.lib.bcel.generic.InstructionHandle; +import com.allatori.lib.bcel.generic.LDC; +import com.allatori.lib.bcel.generic.MethodGen; +import com.allatori.model.ClassStorage; + +public class ClassConstantPoolTransformer implements ClassTransformer { + + public ClassStorage classStorage; + + public ConstantPoolEditor constantPoolEditor; + + public ClassConstantPoolTransformer(ClassStorage classStorage2) { + super(); + this.constantPoolEditor = new ConstantPoolEditor(null); + this.classStorage = classStorage2; + } + + @Override + public void finish() { + DistributedStringEncryptionTransformer.entries6 = null; + DistributedStringEncryptionTransformer.values = null; + } + + @Override + public void transform(ClassGen classGen) { + if (DistributedStringEncryptionTransformer.values.contains(classGen)) { + try { + this.transform2(classGen); + } catch (Exception exception) { + this.constantPoolEditor.processClassGen(classGen); + this.transform2(classGen); + } + } + } + + public void transform2(ClassGen classGen) { + InstructionHandle instructionHandle; + Method[] methods = classGen.getMethods(); + int value; + for (int value2 = value = 0; value2 < methods.length; value2 = ++value) { + Method method; + if ((method = methods[value]).getCode() != null) { + InstructionHandle instructionHandle2; + MethodGen methodGen; + InstructionHandle instructionHandle3 = + instructionHandle2 = + (methodGen = + MethodFactory.createMethodGen( + method, + classGen.getClassName(), + classGen.getConstantPool(), + classGen.getConstantPool().getConstantPool())) + .getInstructionList() + .getStart(); + while (instructionHandle3 != null) { + label38: + { + if (instructionHandle2.getInstruction() instanceof LDC) { + LDC lDC = (LDC) instructionHandle2.getInstruction(); + Constant constant; + if ((constant = classGen.getConstantPool().getConstant(lDC.getIndex())) + instanceof ConstantString) { + String text3; + if ((text3 = + ((ConstantUtf8) + classGen + .getConstantPool() + .getConstant(((ConstantString) constant).getStringIndex())) + .getBytes()) + != null + && text3.startsWith(DistributedStringEncryptionTransformer.text2)) { + String text4 = + text3.substring(DistributedStringEncryptionTransformer.text2.length()); + String text5; + String text6 = + text4.substring( + (text5 = + text4.substring( + 0, + text4.indexOf( + DistributedStringEncryptionTransformer.text2))) + .length() + + DistributedStringEncryptionTransformer.text2.length()); + instructionHandle = instructionHandle2; + lDC.setIndex( + classGen + .getConstantPool() + .addString( + DistributedStringEncryptionTransformer.createText( + text6, classGen.getClassName(), methodGen.getName(), text5))); + break label38; + } + if (text3 != null && text3.startsWith(CustomStringEncryption.text)) { + lDC.setIndex( + classGen + .getConstantPool() + .addString( + CustomStringEncryption.createText( + text3, + this.classStorage.getClassLoader(), + classGen.getClassName(), + methodGen.getName()))); + } + } + } + instructionHandle = instructionHandle2; + } + instructionHandle3 = instructionHandle2 = instructionHandle.getInstructionHandle2(); + } + methodGen.update5(); + classGen.replaceMethod(method, methodGen.getMethod()); + } + } + } +} diff --git a/src/main/java/com/allatori/transform/ClassTransformer.java b/src/main/java/com/allatori/transform/ClassTransformer.java new file mode 100644 index 0000000..409df0c --- /dev/null +++ b/src/main/java/com/allatori/transform/ClassTransformer.java @@ -0,0 +1,10 @@ +package com.allatori.transform; + +import com.allatori.lib.bcel.generic.ClassGen; + +public interface ClassTransformer { + + void transform(ClassGen classGen); + + void finish(); +} diff --git a/src/main/java/com/allatori/transform/ControlFlowTransformer.java b/src/main/java/com/allatori/transform/ControlFlowTransformer.java new file mode 100644 index 0000000..1839343 --- /dev/null +++ b/src/main/java/com/allatori/transform/ControlFlowTransformer.java @@ -0,0 +1,221 @@ +package com.allatori.transform; + +import com.allatori.bytecode.MethodFactory; +import com.allatori.config.Configuration; +import com.allatori.lib.bcel.classfile.Method; +import com.allatori.lib.bcel.generic.ACONST_NULL; +import com.allatori.lib.bcel.generic.ANEWARRAY; +import com.allatori.lib.bcel.generic.BIPUSH; +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.lib.bcel.generic.DLOAD; +import com.allatori.lib.bcel.generic.ICONST; +import com.allatori.lib.bcel.generic.Instruction; +import com.allatori.lib.bcel.generic.InstructionConstants; +import com.allatori.lib.bcel.generic.InstructionHandle; +import com.allatori.lib.bcel.generic.InstructionList; +import com.allatori.lib.bcel.generic.InstructionTargeter; +import com.allatori.lib.bcel.generic.LLOAD; +import com.allatori.lib.bcel.generic.LineNumberGen; +import com.allatori.lib.bcel.generic.LoadInstruction; +import com.allatori.lib.bcel.generic.LocalVariableGen; +import com.allatori.lib.bcel.generic.MethodGen; +import com.allatori.lib.bcel.generic.NEW; +import com.allatori.lib.bcel.generic.NEWARRAY; +import com.allatori.lib.bcel.generic.PUSH; +import com.allatori.lib.bcel.generic.SIPUSH; +import com.allatori.model.ClassStorage; + +public class ControlFlowTransformer implements ClassTransformer { + + public ClassStorage classStorage; + + @Override + public void finish() {} + + @Override + public void transform(ClassGen classGen) { + InstructionHandle instructionHandle; + try { + Method[] methods = classGen.getMethods(); + int value = methods.length; + for (int index = 0; index < value; index++) { + Method method; + if ((method = methods[index]).getCode() != null) { + MethodGen methodGen = + MethodFactory.createMethodGen( + method, + classGen.getClassName(), + classGen.getConstantPool(), + classGen.getConstantPool().getConstantPool()); + if (Configuration.getObfuscationOptions() + .matchesMethodGen(this.classStorage, classGen, methodGen)) { + int value2; + int value3 = + value2 = + Configuration.getExtensiveFlowOptions() + .calculateCount(this.classStorage, classGen, methodGen); + Configuration.getExtensiveFlowOptions(); + if (value3 != 0) { + InstructionList instructionList; + InstructionHandle start = + (instructionList = methodGen.getInstructionList()).getStart(); + byte value4 = 0; + InstructionHandle instructionHandle2 = start; + while (instructionHandle2 != null) { + if (!(start.getInstruction() instanceof NEWARRAY) + && !(start.getInstruction() instanceof ANEWARRAY)) { + label115: + { + label114: + if (start.getInstruction() instanceof NEW) { + if (value4 != 0) { + Configuration.getExtensiveFlowOptions(); + if (value2 != 2) { + break label114; + } + } + if (start.getInstructionHandle() == null) { + instructionHandle = start; + break label115; + } + if (!this.matchesInstructionTargeters(start.getTargeters())) { + instructionHandle = start; + break label115; + } + if (!this.matchesInstructionTargeters( + start.getInstructionHandle().getTargeters())) { + instructionHandle = start; + break label115; + } + if (!(start.getInstructionHandle().getInstruction() instanceof ICONST) + && !(start.getInstructionHandle().getInstruction() + instanceof ACONST_NULL)) { + instructionHandle = start; + break label115; + } + Instruction instruction = start.getInstructionHandle().getInstruction(); + instructionList.createInstructionHandle2( + instructionList.createInstructionHandle2( + instructionList.createInstructionHandle2(start, instruction), + InstructionConstants.DUP), + InstructionConstants.POP2); + value4 = 1; + } + instructionHandle = start; + } + label98: + { + label97: + if (instructionHandle.getInstruction() instanceof NEW) { + if (value4 != 0) { + Configuration.getExtensiveFlowOptions(); + if (value2 != 2) { + break label97; + } + } + if (start.getInstructionHandle() == null) { + value3 = value2; + break label98; + } + if (!this.matchesInstructionTargeters(start.getTargeters())) { + value3 = value2; + break label98; + } + if (!this.matchesInstructionTargeters( + start.getInstructionHandle().getTargeters())) { + value3 = value2; + break label98; + } + if (!(start.getInstructionHandle().getInstruction() + instanceof LoadInstruction)) { + value3 = value2; + break label98; + } + LoadInstruction loadInstruction; + if (!((loadInstruction = + (LoadInstruction) start.getInstructionHandle().getInstruction()) + instanceof LLOAD)) { + if (loadInstruction instanceof DLOAD) { + value3 = value2; + break label98; + } + instructionList.createInstructionHandle2( + instructionList.createInstructionHandle2( + instructionList.createInstructionHandle2( + start, loadInstruction.copy()), + InstructionConstants.DUP), + InstructionConstants.POP2); + value4 = 1; + } + } + value3 = value2; + } + Configuration.getExtensiveFlowOptions(); + if (value3 != 2 + || !(start.getInstruction() instanceof BIPUSH) + && !(start.getInstruction() instanceof SIPUSH) + && !(start.getInstruction() instanceof ICONST)) { + instructionHandle2 = start = start.getInstructionHandle2(); + } else { + instructionList.createInstructionHandle2( + instructionList.createInstructionHandle2( + instructionList.getInstructionHandle2( + start, new PUSH(classGen.getConstantPool(), 1)), + InstructionConstants.DUP), + InstructionConstants.POP2); + start = + start + .getInstructionHandle2() + .getInstructionHandle2() + .getInstructionHandle2() + .getInstructionHandle2(); + instructionHandle2 = start; + } + } else { + instructionList.createInstructionHandle2( + instructionList.createInstructionHandle2( + instructionList.getInstructionHandle2( + start, new PUSH(classGen.getConstantPool(), 1)), + InstructionConstants.DUP), + InstructionConstants.POP2); + start = + start + .getInstructionHandle2() + .getInstructionHandle2() + .getInstructionHandle2() + .getInstructionHandle2(); + instructionHandle2 = start; + } + } + methodGen.update5(); + methodGen.update4(); + classGen.replaceMethod(method, methodGen.getMethod()); + } + } + } + } + } catch (Exception exception) { + exception.printStackTrace(); + } + } + + public ControlFlowTransformer(ClassStorage classStorage2) { + super(); + this.classStorage = classStorage2; + } + + public boolean matchesInstructionTargeters(InstructionTargeter[] instructionTargeters) { + if (instructionTargeters == null) { + return true; + } + int value; + for (int value2 = value = 0; value2 < instructionTargeters.length; value2 = ++value) { + InstructionTargeter instructionTargeter; + if (!((instructionTargeter = instructionTargeters[value]) instanceof LineNumberGen) + && !(instructionTargeter instanceof LocalVariableGen)) { + return false; + } + } + return true; + } +} diff --git a/src/main/java/com/allatori/transform/DistributedStringEncryptionTransformer.java b/src/main/java/com/allatori/transform/DistributedStringEncryptionTransformer.java new file mode 100644 index 0000000..9c3b637 --- /dev/null +++ b/src/main/java/com/allatori/transform/DistributedStringEncryptionTransformer.java @@ -0,0 +1,1331 @@ +package com.allatori.transform; + +import com.allatori.bytecode.ConstantPoolEditor; +import com.allatori.bytecode.MethodFactory; +import com.allatori.config.Configuration; +import com.allatori.crypto.CustomStringEncryption; +import com.allatori.crypto.StringEncryptionUtils; +import com.allatori.internal.NameSignatureInstructionSupport; +import com.allatori.lib.bcel.classfile.Constant; +import com.allatori.lib.bcel.classfile.ConstantString; +import com.allatori.lib.bcel.classfile.ConstantUtf8; +import com.allatori.lib.bcel.classfile.Method; +import com.allatori.lib.bcel.generic.ArrayType; +import com.allatori.lib.bcel.generic.BranchHandle; +import com.allatori.lib.bcel.generic.BranchInstruction; +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.lib.bcel.generic.ConstantPoolGen; +import com.allatori.lib.bcel.generic.IINC; +import com.allatori.lib.bcel.generic.Instruction; +import com.allatori.lib.bcel.generic.InstructionConstants; +import com.allatori.lib.bcel.generic.InstructionFactory; +import com.allatori.lib.bcel.generic.InstructionHandle; +import com.allatori.lib.bcel.generic.InstructionList; +import com.allatori.lib.bcel.generic.LDC; +import com.allatori.lib.bcel.generic.MethodGen; +import com.allatori.lib.bcel.generic.ObjectType; +import com.allatori.lib.bcel.generic.PUSH; +import com.allatori.lib.bcel.generic.Type; +import com.allatori.model.ClassStorage; +import com.allatori.util.Log; +import com.allatori.util.random.RandomUtils; +import java.util.Collection; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.TreeSet; +import java.util.Vector; + +public class DistributedStringEncryptionTransformer implements ClassTransformer { + + public static String text4 = "AllatoriDecryptString"; + + public static String text = "AllatoriDecryptString2"; + + public static String text2 = "allatori-12321-32123:"; + + public static char character = 'U'; + + public static Hashtable entries6 = new Hashtable(); + + public static Type type = Type.STRING; + + public static boolean enabled2 = false; + + public static String text5 = "makeConcatWithConstants"; + + public Hashtable entries; + + public String text3; + + public static Vector values; + + public ClassStorage classStorage; + + public Hashtable entries2; + + public Collection collection; + + public Hashtable entries3; + + public Hashtable entries4; + + public String text6; + + public Hashtable entries5; + + public boolean enabled; + + public Hashtable entries7; + + public Hashtable entries8; + + public static String createText(String text, String text2, String text3, String text4) { + int value = ((int[]) entries6.get(text4))[2] == 0 ? 1 : 0; + String text5 = value != 0 ? ("" + text2 + text3) : ("" + text3 + text2); + int value2 = text5.length() - 1; + int value3 = text5.length() - 1; + char[] values = new char[text.length()]; + char value4 = (char) ((int[]) entries6.get(text4))[0]; + char value5 = (char) ((int[]) entries6.get(text4))[1]; + int value6; + for (int value7 = value6 = values.length - 1; value7 >= 0; value7 = --value6) { + char value8 = (char) (text.charAt(value6) ^ value4 ^ text5.charAt(value3)); + int value9 = value6; + value6--; + values[value9] = value8; + if (value6 < 0) { + break; + } + char value10 = (char) (text.charAt(value6) ^ value5 ^ text5.charAt(value3)); + int value11 = value6; + value3--; + values[value11] = value10; + if (value3 < 0) { + value3 = value2; + } + } + return new String(values); + } + + public void processValues(Vector vector, Vector vector2) { + if (vector == null) { + vector = new Vector(); + } + if (vector2 == null) { + vector2 = new Vector(); + } + if (Configuration.getObfuscationOptions().isEnabled()) { + Iterator iterator2; + Iterator iterator3 = iterator2 = vector.iterator(); + while (iterator3.hasNext()) { + ClassGen classGen = (ClassGen) iterator2.next(); + iterator3 = iterator2; + StringEncryptionUtils.processCharacter(classGen, text4, character); + } + } else { + Iterator iterator4; + Iterator iterator5 = iterator4 = vector.iterator(); + while (iterator5.hasNext()) { + ClassGen classGen2 = (ClassGen) iterator4.next(); + int value = RandomUtils.calculateCount(125) + 1; + int value2 = RandomUtils.calculateCount(125) + 1; + iterator5 = iterator4; + this.entries.put(classGen2.getClassName(), new int[] {value, value2}); + this.transform2(classGen2); + } + Iterator iterator6; + for (Iterator iterator7 = iterator6 = vector2.iterator(); + iterator7.hasNext(); + iterator7 = iterator6) { + ClassGen classGen3 = (ClassGen) iterator6.next(); + int value3 = RandomUtils.calculateCount(125) + 1; + int value4 = RandomUtils.calculateCount(125) + 1; + int value5 = RandomUtils.calculateValue() <= 0.5 ? 0 : 1; + entries6.put(classGen3.getClassName(), new int[] {value3, value4, value5}); + this.transform3(classGen3); + } + } + } + + public DistributedStringEncryptionTransformer(ClassStorage classStorage2) { + super(); + this.collection = new TreeSet(); + this.enabled = true; + this.entries7 = new Hashtable(); + this.entries4 = new Hashtable(); + this.entries3 = new Hashtable(); + this.entries5 = new Hashtable(); + this.entries8 = new Hashtable(); + this.entries2 = new Hashtable(); + this.entries = new Hashtable(); + this.text3 = ".R"; + this.text6 = "org.springframework.boot."; + this.classStorage = classStorage2; + character = Configuration.getObfuscationOptions().getCharacter(); + values = new Vector(); + entries6 = new Hashtable(); + StringEncryptionUtils.update(); + this.collection.add(""); + this.finish2(); + } + + public void processValues(Vector vector) { + DistributedStringEncryptionTransformer distributedStringEncryptionTransformer; + Vector vector2; + if (vector.size() != 0) { + String text; + if ((text = Configuration.getObfuscationOptions().getDecryptorIncludePattern()).length() + > 0) { + String[] texts = text.split(";"); + int value; + for (int value2 = value = vector.size() - 1; value2 >= 0; value2 = --value) { + ClassGen classGen = (ClassGen) vector.get(value); + int value3; + for (int value4 = value3 = texts.length - 1; value4 >= 0; value4 = --value3) { + if (texts[value3].length() > 0 && !classGen.getClassName().startsWith(texts[value3])) { + vector.removeElement(classGen); + } + } + } + } + String text2; + if ((text2 = Configuration.getObfuscationOptions().getDecryptorExcludePattern()).length() + > 0) { + String[] texts2 = text2.split(";"); + int value5; + for (int value6 = value5 = vector.size() - 1; value6 >= 0; value6 = --value5) { + ClassGen classGen2 = (ClassGen) vector.get(value5); + int value7; + for (int value8 = value7 = texts2.length - 1; value8 >= 0; value8 = --value7) { + if (texts2[value7].length() > 0 + && classGen2.getClassName().startsWith(texts2[value7])) { + vector.removeElement(classGen2); + } + } + } + } + ClassGen classGen3 = null; + ClassGen classGen4 = null; + ClassGen classGen5 = null; + String text3 = "java."; + int value9; + int value10 = value9 = vector.size() - 1; + while (true) { + if (value10 < 0) { + vector2 = vector; + break; + } + if (vector.size() == 1) { + vector2 = vector; + break; + } + ClassGen classGen6 = (ClassGen) vector.get(value9); + byte value11 = 1; + if (classGen6.containsMethod((String) "", (String) "()V") != null) { + value11 = 0; + } + byte value12 = 1; + int value13; + if (!classGen6.getSuperclassName().startsWith(text3)) { + value12 = 0; + value13 = value11; + } else { + String[] texts3; + int value14 = (texts3 = classGen6.getInterfaceNames()).length; + int value15; + value13 = value15 = 0; + while (true) { + if (value13 >= value14) { + value13 = value11; + break; + } + if (!texts3[value15].startsWith(text3)) { + value12 = 0; + value13 = value11; + break; + } + value13 = ++value15; + } + } + if (value13 != 0 && classGen3 == null) { + classGen3 = classGen6; + } + if (value12 != 0 && classGen4 == null) { + classGen4 = classGen6; + } + if (value11 != 0 && value12 != 0 && classGen5 == null) { + classGen5 = classGen6; + } + if (value11 == 0 || value12 == 0) { + vector.remove(classGen6); + } + value10 = --value9; + } + label93: + { + if (vector2.size() == 1) { + if (classGen5 != null) { + distributedStringEncryptionTransformer = this; + vector.clear(); + vector.add(classGen5); + break label93; + } + if (classGen4 != null) { + distributedStringEncryptionTransformer = this; + vector.clear(); + vector.add(classGen4); + break label93; + } + if (classGen3 != null) { + vector.clear(); + vector.add(classGen3); + } + } + distributedStringEncryptionTransformer = this; + } + ClassGen classGen7; + if ((classGen7 = + distributedStringEncryptionTransformer.classStorage.getClassGen( + "com.allatori.ant.ObfuscatorTask")) + != null) { + vector.removeElement(classGen7); + } + ClassGen classGen8; + if ((classGen8 = this.classStorage.getClassGen("com.allatori.wtk.WTKObfuscator")) != null) { + vector.removeElement(classGen8); + } + } + } + + public void transform2(ClassGen classGen) { + InstructionFactory instructionFactory = new InstructionFactory(classGen); + ConstantPoolGen constantPool = classGen.getConstantPool(); + InstructionList instructionList = new InstructionList(); + MethodGen methodGen = + new MethodGen( + 9, + Type.STRING, + new Type[] {type}, + new String[] {"s"}, + text4, + classGen.getClassName(), + instructionList, + constantPool); + int value = RandomUtils.calculateValue() <= 0.5 ? 1 : 0; + Vector vector; + Vector vector2; + if (value != 0) { + vector2 = + vector = + StringEncryptionUtils.createValues( + ((int[]) this.entries.get(classGen.getClassName()))[0]); + vector2.addAll(StringEncryptionUtils.createValues(RandomUtils.calculateCount(125) + 1)); + } else { + (vector = StringEncryptionUtils.createValues(RandomUtils.calculateCount(125) + 1)) + .addAll( + StringEncryptionUtils.createValues( + ((int[]) this.entries.get(classGen.getClassName()))[0])); + vector2 = vector; + } + vector2.addAll( + StringEncryptionUtils.createValues(((int[]) this.entries.get(classGen.getClassName()))[1])); + Iterator iterator2 = vector.iterator(); + Iterator iterator3 = iterator2; + while (iterator3.hasNext()) { + Instruction instruction = (Instruction) iterator2.next(); + iterator3 = iterator2; + instructionList.getInstructionHandle(instruction); + } + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.OBJECT, 0)); + instructionList.getInstructionHandle(instructionFactory.createCheckCast(Type.STRING)); + instructionList.getInstructionHandle(InstructionConstants.DUP); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction(Type.OBJECT, 0)); + instructionList.getInstructionHandle( + instructionFactory.createInvoke( + "java.lang.String", "length", Type.INT, Type.NO_ARGS, (short) 182)); + instructionList.getInstructionHandle(InstructionConstants.DUP); + instructionList.getInstructionHandle(instructionFactory.createNewArray(Type.CHAR, (short) 1)); + instructionList.getInstructionHandle(InstructionConstants.SWAP); + instructionList.getInstructionHandle(new PUSH(constantPool, 1)); + instructionList.getInstructionHandle(InstructionConstants.ISUB); + instructionList.getInstructionHandle(InstructionConstants.DUP_X2); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction(Type.INT, 3)); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction(Type.OBJECT, 1)); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction(Type.INT, 4)); + instructionList.getInstructionHandle(InstructionConstants.DUP_X2); + if (value != 0) { + instructionList.getInstructionHandle(InstructionFactory.POP2); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction(Type.INT, 2)); + } else { + instructionList.getInstructionHandle(InstructionFactory.POP); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction(Type.INT, 2)); + instructionList.getInstructionHandle(InstructionFactory.POP); + } + BranchInstruction branchInstruction = + InstructionFactory.createBranchInstruction((short) 155, null); + BranchHandle branchHandle = instructionList.getBranchHandle(branchInstruction); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.OBJECT, 1)); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.OBJECT, 0)); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.INT, 3)); + instructionList.getInstructionHandle(InstructionConstants.DUP_X1); + instructionList.getInstructionHandle( + instructionFactory.createInvoke( + "java.lang.String", "charAt", Type.CHAR, new Type[] {Type.INT}, (short) 182)); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.INT, 2)); + instructionList.getInstructionHandle(InstructionConstants.IXOR); + instructionList.getInstructionHandle(InstructionConstants.I2C); + instructionList.getInstructionHandle(new IINC(3, -1)); + instructionList.getInstructionHandle(InstructionConstants.CASTORE); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.INT, 3)); + BranchInstruction branchInstruction2 = + InstructionFactory.createBranchInstruction((short) 155, null); + instructionList.getBranchHandle(branchInstruction2); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.OBJECT, 1)); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.OBJECT, 0)); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.INT, 3)); + instructionList.getInstructionHandle(InstructionConstants.DUP_X1); + instructionList.getInstructionHandle( + instructionFactory.createInvoke( + "java.lang.String", "charAt", Type.CHAR, new Type[] {Type.INT}, (short) 182)); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.INT, 4)); + instructionList.getInstructionHandle(new IINC(3, -1)); + instructionList.getInstructionHandle(InstructionConstants.IXOR); + instructionList.getInstructionHandle(InstructionConstants.I2C); + instructionList.getInstructionHandle(InstructionConstants.CASTORE); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.INT, 3)); + instructionList.getBranchHandle( + InstructionFactory.createBranchInstruction((short) 167, branchHandle)); + InstructionHandle instructionHandle = + instructionList.getInstructionHandle(instructionFactory.createNew("java.lang.String")); + instructionList.getInstructionHandle(InstructionConstants.DUP); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.OBJECT, 1)); + instructionList.getInstructionHandle( + instructionFactory.createInvoke( + "java.lang.String", + "", + Type.VOID, + new Type[] {new ArrayType(Type.CHAR, 1)}, + (short) 183)); + instructionList.getInstructionHandle(InstructionFactory.createReturn(Type.OBJECT)); + branchInstruction.setTarget(instructionHandle); + branchInstruction2.setTarget(instructionHandle); + methodGen.update5(); + methodGen.update4(); + classGen.processMethod2(methodGen.getMethod()); + instructionList.update3(); + } + + public boolean isEnabled() { + return this.enabled; + } + + @Override + public void finish() {} + + public boolean matchesClassGen(ClassGen classGen) { + return Configuration.getObfuscationOptions().isPackageStringEncryptionEnabled() + ? !classGen.isEnabled9() + && !classGen.isEnabled2() + && !classGen.isEnabled10() + && !classGen.isEnabled5() + && !classGen.isEnabled8() + && !classGen.getClassName().contains("$") + && !classGen.getClassName().endsWith(this.text3) + : classGen.isEnabled6() + && !classGen.isEnabled2() + && !classGen.isEnabled10() + && !classGen.isEnabled5() + && !classGen.isEnabled8() + && !classGen.getClassName().contains("$") + && !classGen.getClassName().endsWith(this.text3); + } + + @Override + public void transform(ClassGen classGen) { + InstructionHandle instructionHandle; + byte value = 0; + Iterator iterator2 = this.entries7.values().iterator(); + int value2; + while (true) { + if (iterator2.hasNext()) { + if (!((Vector) iterator2.next()).contains(classGen)) { + continue; + } + value2 = 1; + break; + } + value2 = value; + break; + } + if (value2 != 0) { + InstructionFactory instructionFactory = new InstructionFactory(classGen); + byte value3 = 2; + String[] texts = new String[2]; + int value4; + if (((Vector) this.entries3.get(this.getText(classGen))).size() > 0) { + for (int value5 = value4 = 0; value5 < value3; value5 = value4) { + String className = + ((ClassGen) + ((Vector) this.entries3.get(this.getText(classGen))) + .get( + RandomUtils.calculateCount( + ((Vector) this.entries3.get(this.getText(classGen))).size()))) + .getClassName(); + int value6 = value4; + value4++; + texts[value6] = className; + } + } + int value7 = 0; + String[] texts2 = new String[value3]; + int value8; + if (((Vector) this.entries5.get(this.getText(classGen))).size() > 0) { + for (int value9 = value8 = 0; value9 < value3; value9 = value8) { + String className2 = + ((ClassGen) + ((Vector) this.entries5.get(this.getText(classGen))) + .get( + RandomUtils.calculateCount( + ((Vector) this.entries5.get(this.getText(classGen))).size()))) + .getClassName(); + int value10 = value8; + value8++; + texts2[value10] = className2; + } + } + int value11 = 0; + Method[] methods = classGen.getMethods(); + int value12; + for (value2 = value12 = 0; value2 < methods.length; value2 = ++value12) { + Method method; + if ((method = methods[value12]).getCode() != null) { + if (classGen.getConstantPool().getSize() > 20000) { + new ConstantPoolEditor(this.classStorage).processClassGen(classGen); + instructionFactory = new InstructionFactory(classGen); + method = (methods = classGen.getMethods())[value12]; + } + InstructionHandle instructionHandle2; + InstructionList instructionList; + MethodGen methodGen; + InstructionHandle instructionHandle3 = + instructionHandle2 = + (instructionList = + (methodGen = + MethodFactory.createMethodGen( + method, + classGen.getClassName(), + classGen.getConstantPool(), + classGen.getConstantPool().getConstantPool())) + .getInstructionList()) + .getStart(); + while (instructionHandle3 != null) { + label156: + { + if (!enabled2 + && instructionHandle2.getInstruction() + instanceof NameSignatureInstructionSupport) { + NameSignatureInstructionSupport nameSignatureInstructionSupport = + (NameSignatureInstructionSupport) instructionHandle2.getInstruction(); + if (text5.equals( + nameSignatureInstructionSupport.getText3(classGen.getConstantPool()))) { + Log.warn( + "javac Java compiler should be run with -XDstringConcat=inline flag to" + + " encrypt all strings."); + enabled2 = true; + } + } else if (instructionHandle2.getInstruction() instanceof LDC) { + LDC lDC = (LDC) instructionHandle2.getInstruction(); + Constant constant; + if ((constant = classGen.getConstantPool().getConstant(lDC.getIndex())) + instanceof ConstantString) { + String bytes = + ((ConstantUtf8) + classGen + .getConstantPool() + .getConstant(((ConstantString) constant).getStringIndex())) + .getBytes(); + if (this.classStorage.getClassGen(bytes) != null + || this.collection.contains(bytes) + || StringEncryptionUtils.matchesText(bytes)) { + instructionHandle3 = + instructionHandle2 = instructionHandle2.getInstructionHandle2(); + continue; + } + int value13; + label107: + { + value13 = + Configuration.getObfuscationOptions() + .calculateCount(this.classStorage, classGen, methodGen); + String text3; + if ((text3 = classGen.getClassName()).startsWith((String) "com.allatori")) { + if (text3.startsWith("com.allatori.obfuscate.opt")) { + Configuration.getObfuscationOptions(); + value13 = 0; + } + if (text3.startsWith("com.allatori.obfuscate.ren")) { + Configuration.getObfuscationOptions(); + value13 = 0; + } + if (text3.startsWith("com.allatori.io.re")) { + Configuration.getObfuscationOptions(); + value13 = 0; + value2 = value13; + break label107; + } + } else if (text3.startsWith((String) "org.apache.bcel")) { + Configuration.getObfuscationOptions(); + value13 = 0; + } + value2 = value13; + } + Configuration.getObfuscationOptions(); + if (value2 == 1) { + String text6 = texts2[value11]; + lDC.setIndex( + classGen.getConstantPool().addString("" + text2 + text6 + text2 + bytes)); + String text7 = text; + ObjectType objectType = Type.STRING; + Type[] types = new Type[] {type}; + InstructionFactory instructionFactory2 = instructionFactory; + InstructionHandle instructionHandle4 = instructionHandle2; + InstructionList instructionList2 = instructionList; + value11++; + instructionList2.createInstructionHandle2( + instructionHandle4, + instructionFactory2.createInvoke( + text6, text7, objectType, types, (short) 184)); + if (value11 >= value3) { + value11 = 0; + } + if (!values.contains(classGen)) { + values.add(classGen); + } + } else { + Configuration.getObfuscationOptions(); + if (value13 >= 1000) { + String text8; + if ((text8 = + CustomStringEncryption.createText( + bytes, value13, this.classStorage.getClassLoader())) + .startsWith(CustomStringEncryption.text) + && !values.contains(classGen)) { + values.add(classGen); + } + lDC.setIndex(classGen.getConstantPool().addString(text8)); + instructionHandle = instructionHandle2; + instructionList.createInstructionHandle2( + instructionHandle2, + CustomStringEncryption.getInvokeInstruction(instructionFactory, value13)); + break label156; + } + String text9 = texts[value7]; + lDC.setIndex( + classGen.getConstantPool().addString(this.createText(bytes, text9))); + String text10 = text4; + ObjectType objectType2 = Type.STRING; + Type[] types2 = new Type[] {type}; + InstructionFactory instructionFactory3 = instructionFactory; + InstructionHandle instructionHandle5 = instructionHandle2; + InstructionList instructionList3 = instructionList; + value7++; + instructionList3.createInstructionHandle2( + instructionHandle5, + instructionFactory3.createInvoke( + text9, text10, objectType2, types2, (short) 184)); + if (value7 >= value3) { + value7 = 0; + } + } + } + } + instructionHandle = instructionHandle2; + } + instructionHandle3 = instructionHandle2 = instructionHandle.getInstructionHandle2(); + } + methodGen.update5(); + try { + classGen.replaceMethod(method, methodGen.getMethod()); + } catch (Exception exception) { + Log.error( + "Error processing " + + classGen.getClassName() + + "." + + methodGen.getName() + + " " + + exception.getMessage()); + } + } + } + } + } + + public void transform3(ClassGen classGen) { + InstructionFactory instructionFactory = new InstructionFactory(classGen); + ConstantPoolGen constantPool = classGen.getConstantPool(); + InstructionList instructionList = new InstructionList(); + MethodGen methodGen = + new MethodGen( + 9, + Type.STRING, + new Type[] {type}, + new String[] {"arg0"}, + text, + classGen.getClassName(), + instructionList, + constantPool); + instructionList.getInstructionHandle(instructionFactory.createNew("java.lang.StringBuffer")); + instructionList.getInstructionHandle(InstructionConstants.DUP); + String text2 = "java.lang.RuntimeException"; + instructionList.getInstructionHandle(instructionFactory.createNew(text2)); + instructionList.getInstructionHandle(InstructionConstants.DUP); + instructionList.getInstructionHandle( + instructionFactory.createInvoke(text2, "", Type.VOID, Type.NO_ARGS, (short) 183)); + instructionList.getInstructionHandle( + instructionFactory.createInvoke( + text2, + "getStackTrace", + new ArrayType(new ObjectType("java.lang.StackTraceElement"), 1), + Type.NO_ARGS, + (short) 182)); + instructionList.getInstructionHandle(new PUSH(constantPool, 1)); + instructionList.getInstructionHandle(InstructionConstants.AALOAD); + instructionList.getInstructionHandle(InstructionConstants.DUP_X2); + int value = ((int[]) entries6.get(classGen.getClassName()))[2] == 0 ? 1 : 0; + int value2 = RandomUtils.calculateValue() > 0.5 ? 1 : 0; + InstructionList instructionList2; + if (value2 != 0) { + instructionList.getInstructionHandle( + instructionFactory.createInvoke( + "java.lang.StackTraceElement", + value != 0 ? "getClassName" : "getMethodName", + Type.STRING, + Type.NO_ARGS, + (short) 182)); + instructionList2 = instructionList; + } else { + instructionList.getInstructionHandle( + instructionFactory.createInvoke( + "java.lang.StackTraceElement", + value != 0 ? "getMethodName" : "getClassName", + Type.STRING, + Type.NO_ARGS, + (short) 182)); + instructionList2 = instructionList; + } + instructionList2.getInstructionHandle( + instructionFactory.createInvoke( + "java.lang.StringBuffer", "", Type.VOID, new Type[] {Type.STRING}, (short) 183)); + instructionList.getInstructionHandle(InstructionConstants.SWAP); + if (value2 != 0) { + instructionList.getInstructionHandle( + instructionFactory.createInvoke( + "java.lang.StackTraceElement", + value != 0 ? "getMethodName" : "getClassName", + Type.STRING, + Type.NO_ARGS, + (short) 182)); + instructionList.getInstructionHandle( + instructionFactory.createInvoke( + "java.lang.StringBuffer", + "append", + Type.STRINGBUFFER, + new Type[] {Type.STRING}, + (short) 182)); + instructionList2 = instructionList; + } else { + instructionList.getInstructionHandle( + instructionFactory.createInvoke( + "java.lang.StackTraceElement", + value != 0 ? "getClassName" : "getMethodName", + Type.STRING, + Type.NO_ARGS, + (short) 182)); + instructionList.getInstructionHandle(InstructionConstants.ICONST_0); + instructionList.getInstructionHandle(InstructionConstants.SWAP); + instructionList.getInstructionHandle( + instructionFactory.createInvoke( + "java.lang.StringBuffer", + "insert", + Type.STRINGBUFFER, + new Type[] {Type.INT, Type.STRING}, + (short) 182)); + instructionList2 = instructionList; + } + instructionList2.getInstructionHandle( + instructionFactory.createInvoke( + "java.lang.StringBuffer", "toString", Type.STRING, Type.NO_ARGS, (short) 182)); + instructionList.getInstructionHandle(InstructionConstants.DUP); + instructionList.getInstructionHandle( + instructionFactory.createInvoke( + "java.lang.String", "length", Type.INT, Type.NO_ARGS, (short) 182)); + instructionList.getInstructionHandle(new PUSH(constantPool, 1)); + instructionList.getInstructionHandle(InstructionConstants.ISUB); + int value3 = RandomUtils.calculateValue() <= 0.5 ? 1 : 0; + Vector vector; + Vector vector2; + if (value3 != 0) { + vector2 = + vector = + StringEncryptionUtils.createValues( + ((int[]) entries6.get(classGen.getClassName()))[0]); + vector2.addAll(StringEncryptionUtils.createValues(RandomUtils.calculateCount(125) + 1)); + } else { + (vector = StringEncryptionUtils.createValues(RandomUtils.calculateCount(125) + 1)) + .addAll( + StringEncryptionUtils.createValues( + ((int[]) entries6.get(classGen.getClassName()))[0])); + vector2 = vector; + } + vector2.addAll( + StringEncryptionUtils.createValues(((int[]) entries6.get(classGen.getClassName()))[1])); + instructionList.getInstructionHandle(InstructionConstants.FCONST_2); + instructionList.getInstructionHandle(InstructionConstants.FCONST_1); + instructionList.getInstructionHandle(InstructionConstants.POP); + Iterator iterator2 = vector.iterator(); + Iterator iterator3 = iterator2; + while (iterator3.hasNext()) { + Instruction instruction = (Instruction) iterator2.next(); + iterator3 = iterator2; + instructionList.getInstructionHandle(instruction); + } + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.OBJECT, 0)); + instructionList.getInstructionHandle(instructionFactory.createCheckCast(Type.STRING)); + instructionList.getInstructionHandle(InstructionConstants.DUP); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction(Type.OBJECT, 0)); + instructionList.getInstructionHandle( + instructionFactory.createInvoke( + "java.lang.String", "length", Type.INT, Type.NO_ARGS, (short) 182)); + instructionList.getInstructionHandle(InstructionConstants.DUP); + instructionList.getInstructionHandle(instructionFactory.createNewArray(Type.CHAR, (short) 1)); + instructionList.getInstructionHandle(InstructionConstants.SWAP); + instructionList.getInstructionHandle(new PUSH(constantPool, 1)); + instructionList.getInstructionHandle(InstructionConstants.ISUB); + instructionList.getInstructionHandle(InstructionConstants.DUP_X2); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction(Type.INT, 1)); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction(Type.OBJECT, 3)); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction(Type.INT, 7)); + if (value3 != 0) { + instructionList.getInstructionHandle(InstructionConstants.DUP_X2); + instructionList.getInstructionHandle(InstructionConstants.POP2); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction(Type.INT, 4)); + instructionList2 = instructionList; + } else { + instructionList.getInstructionHandle(InstructionConstants.DUP_X2); + instructionList.getInstructionHandle(InstructionConstants.POP); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction(Type.INT, 4)); + instructionList.getInstructionHandle(InstructionConstants.POP); + instructionList2 = instructionList; + } + instructionList2.getInstructionHandle(InstructionConstants.SWAP); + instructionList.getInstructionHandle(InstructionConstants.POP); + instructionList.getInstructionHandle(InstructionConstants.SWAP); + instructionList.getInstructionHandle(InstructionConstants.DUP); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction(Type.INT, 2)); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction(Type.INT, 5)); + instructionList.getInstructionHandle(InstructionConstants.SWAP); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction(Type.OBJECT, 6)); + BranchInstruction branchInstruction = + InstructionFactory.createBranchInstruction((short) 167, null); + instructionList.getBranchHandle(branchInstruction); + InstructionHandle instructionHandle = + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.OBJECT, 3)); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.INT, 4)); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.OBJECT, 0)); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.INT, 1)); + instructionList.getInstructionHandle(InstructionConstants.DUP_X2); + instructionList.getInstructionHandle( + instructionFactory.createInvoke( + "java.lang.String", "charAt", Type.CHAR, new Type[] {Type.INT}, (short) 182)); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.OBJECT, 6)); + instructionList.getInstructionHandle(new IINC(1, -1)); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.INT, 2)); + instructionList.getInstructionHandle( + instructionFactory.createInvoke( + "java.lang.String", "charAt", Type.CHAR, new Type[] {Type.INT}, (short) 182)); + instructionList.getInstructionHandle(InstructionConstants.IXOR); + instructionList.getInstructionHandle(InstructionConstants.IXOR); + instructionList.getInstructionHandle(InstructionConstants.I2C); + instructionList.getInstructionHandle(InstructionConstants.CASTORE); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.INT, 1)); + BranchInstruction branchInstruction2 = + InstructionFactory.createBranchInstruction((short) 156, null); + instructionList.getBranchHandle(branchInstruction2); + BranchInstruction branchInstruction3 = + InstructionFactory.createBranchInstruction((short) 167, null); + instructionList.getBranchHandle(branchInstruction3); + InstructionHandle instructionHandle2 = + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.OBJECT, 3)); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.INT, 7)); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.OBJECT, 0)); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.INT, 1)); + instructionList.getInstructionHandle(InstructionConstants.DUP_X2); + instructionList.getInstructionHandle( + instructionFactory.createInvoke( + "java.lang.String", "charAt", Type.CHAR, new Type[] {Type.INT}, (short) 182)); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.OBJECT, 6)); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.INT, 2)); + instructionList.getInstructionHandle( + instructionFactory.createInvoke( + "java.lang.String", "charAt", Type.CHAR, new Type[] {Type.INT}, (short) 182)); + instructionList.getInstructionHandle(InstructionConstants.IXOR); + instructionList.getInstructionHandle(new IINC(2, -1)); + instructionList.getInstructionHandle(InstructionConstants.IXOR); + instructionList.getInstructionHandle(InstructionConstants.I2C); + instructionList.getInstructionHandle(new IINC(1, -1)); + instructionList.getInstructionHandle(InstructionConstants.CASTORE); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.INT, 2)); + BranchInstruction branchInstruction4 = + InstructionFactory.createBranchInstruction((short) 156, null); + instructionList.getBranchHandle(branchInstruction4); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.INT, 5)); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction(Type.INT, 2)); + InstructionHandle instructionHandle3 = + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.INT, 1)); + BranchHandle branchHandle = + instructionList.getBranchHandle( + InstructionFactory.createBranchInstruction((short) 156, instructionHandle)); + InstructionHandle instructionHandle4 = + instructionList.getInstructionHandle(instructionFactory.createNew("java.lang.String")); + instructionList.getInstructionHandle(InstructionConstants.DUP); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.OBJECT, 3)); + instructionList.getInstructionHandle( + instructionFactory.createInvoke( + "java.lang.String", + "", + Type.VOID, + new Type[] {new ArrayType(Type.CHAR, 1)}, + (short) 183)); + instructionList.getInstructionHandle(InstructionFactory.createReturn(Type.OBJECT)); + branchInstruction.setTarget(branchHandle); + branchInstruction2.setTarget(instructionHandle2); + branchInstruction3.setTarget(instructionHandle4); + branchInstruction4.setTarget(instructionHandle3); + methodGen.update5(); + methodGen.update4(); + classGen.processMethod2(methodGen.getMethod()); + instructionList.update3(); + } + + public boolean matchesBoolean(Boolean matches) { + return matches == null ? false : matches; + } + + public boolean matchesClassGen2(ClassGen classGen) { + int value = Configuration.getObfuscationOptions().calculateCount(this.classStorage, classGen); + Configuration.getObfuscationOptions(); + if (value == 0) { + return false; + } + String text = this.getText(classGen); + byte value2 = 0; + Method[] methods; + int value3 = (methods = classGen.getMethods()).length; + int value4; + for (value = value4 = 0; value < value3; value = ++value4) { + Method method; + if ((method = methods[value4]).getCode() != null) { + InstructionHandle instructionHandle; + MethodGen methodGen; + InstructionHandle instructionHandle2 = + instructionHandle = + (methodGen = + MethodFactory.createMethodGen( + method, + classGen.getClassName(), + classGen.getConstantPool(), + classGen.getConstantPool().getConstantPool())) + .getInstructionList() + .getStart(); + while (instructionHandle2 != null) { + if (instructionHandle.getInstruction() instanceof LDC) { + LDC lDC = (LDC) instructionHandle.getInstruction(); + Constant constant; + if ((constant = classGen.getConstantPool().getConstant(lDC.getIndex())) + instanceof ConstantString) { + String bytes = + ((ConstantUtf8) + classGen + .getConstantPool() + .getConstant(((ConstantString) constant).getStringIndex())) + .getBytes(); + if (this.classStorage.getClassGen(bytes) != null + || this.collection.contains(bytes) + || StringEncryptionUtils.matchesText(bytes)) { + instructionHandle2 = instructionHandle = instructionHandle.getInstructionHandle2(); + continue; + } + label56: + { + int value5 = + Configuration.getObfuscationOptions() + .calculateCount(this.classStorage, classGen, methodGen); + String text2; + if ((text2 = classGen.getClassName()).startsWith((String) "com.allatori")) { + if (text2.startsWith("com.allatori.obfuscate.opt")) { + Configuration.getObfuscationOptions(); + value5 = 0; + } + if (text2.startsWith("com.allatori.obfuscate.ren")) { + Configuration.getObfuscationOptions(); + value5 = 0; + } + if (text2.startsWith("com.allatori.io.re")) { + Configuration.getObfuscationOptions(); + byte value6 = 0; + value = value6; + break label56; + } + } else if (text2.startsWith((String) "org.apache.bcel")) { + Configuration.getObfuscationOptions(); + value5 = 0; + } + value = value5; + } + Configuration.getObfuscationOptions(); + if (value == 1) { + value2 = 1; + this.entries2.put(text, true); + if (this.matchesBoolean((Boolean) this.entries8.get(text))) { + return true; + } + } else { + value2 = 1; + this.entries8.put(text, true); + if (this.matchesBoolean((Boolean) this.entries2.get(text))) { + return true; + } + } + } + } + instructionHandle2 = instructionHandle = instructionHandle.getInstructionHandle2(); + } + } + } + return value2 != 0; + } + + public void processValues2(Vector vector) { + if (vector.size() != 0) { + String text = this.getText((ClassGen) vector.get(0)); + int value = + this.entries7.get(text) == null ? 0 : ((Vector) this.entries7.get(text)).size() / 8; + if (value == 0) { + value = 1; + } + int value2; + if ((value2 = vector.size() / value) == 0) { + value2 = 1; + } + Vector vector2; + Vector vector3; + DistributedStringEncryptionTransformer distributedStringEncryptionTransformer; + label108: + { + vector3 = new Vector(); + vector2 = new Vector(); + if (vector.size() < value2 + 1) { + if (vector.size() == 1) { + if (this.matchesBoolean((Boolean) this.entries8.get(text))) { + vector3.add(vector.get(0)); + } + if (this.matchesBoolean((Boolean) this.entries2.get(text))) { + distributedStringEncryptionTransformer = this; + vector2.add(vector.get(0)); + break label108; + } + } else if (vector.size() == 2) { + if (this.matchesBoolean((Boolean) this.entries8.get(text))) { + vector3.add(vector.get(0)); + } + if (this.matchesBoolean((Boolean) this.entries2.get(text))) { + vector2.add(vector.get(0)); + } + if (this.matchesBoolean((Boolean) this.entries8.get(text))) { + vector3.add(vector.get(1)); + } + if (this.matchesBoolean((Boolean) this.entries2.get(text))) { + distributedStringEncryptionTransformer = this; + vector2.add(vector.get(1)); + break label108; + } + } else if (vector.size() == 3) { + if (this.matchesBoolean((Boolean) this.entries8.get(text))) { + vector3.add(vector.get(0)); + } + if (this.matchesBoolean((Boolean) this.entries2.get(text))) { + vector2.add(vector.get(0)); + } + if (this.matchesBoolean((Boolean) this.entries8.get(text))) { + vector3.add(vector.get(1)); + } + if (this.matchesBoolean((Boolean) this.entries2.get(text))) { + distributedStringEncryptionTransformer = this; + vector2.add(vector.get(2)); + break label108; + } + } else { + if (this.matchesBoolean((Boolean) this.entries8.get(text))) { + vector3.add(vector.get(0)); + } + if (this.matchesBoolean((Boolean) this.entries2.get(text))) { + vector2.add(vector.get(1)); + } + if (this.matchesBoolean((Boolean) this.entries8.get(text))) { + vector3.add(vector.get(2)); + } + if (this.matchesBoolean((Boolean) this.entries2.get(text))) { + distributedStringEncryptionTransformer = this; + vector2.add(vector.get(3)); + break label108; + } + } + } else { + int value3; + int value4 = value3 = 0; + while (value4 < vector.size()) { + int value5; + if (this.matchesBoolean((Boolean) this.entries8.get(text))) { + value5 = value3; + vector3.add(vector.get(value3)); + } else { + if (this.matchesBoolean((Boolean) this.entries2.get(text))) { + vector2.add(vector.get(value3)); + } + value5 = value3; + } + int value6; + if ((value6 = value5 + value2) >= vector.size()) { + distributedStringEncryptionTransformer = this; + break label108; + } + int value7; + if (this.matchesBoolean((Boolean) this.entries2.get(text))) { + value7 = value6; + vector2.add(vector.get(value6)); + } else { + if (this.matchesBoolean((Boolean) this.entries8.get(text))) { + vector3.add(vector.get(value6)); + } + value7 = value6; + } + value4 = value3 = value7 + value2; + } + } + distributedStringEncryptionTransformer = this; + } + distributedStringEncryptionTransformer.entries3.put(text, vector3); + this.entries5.put(text, vector2); + } + } + + public void finish2() { + Iterator classesByName2 = this.classStorage.getClassesByName2(); + label133: + while (true) { + for (Iterator iterator2 = classesByName2; iterator2.hasNext(); iterator2 = classesByName2) { + ClassGen classGen = (ClassGen) classesByName2.next(); + if (!Configuration.getIgnoreClassesOptions().matchesClassGen(this.classStorage, classGen)) { + int value; + int value2 = + value = + Configuration.getObfuscationOptions().calculateCount(this.classStorage, classGen); + Configuration.getObfuscationOptions(); + if (value2 == 1) { + StringEncryptionUtils.processCollection(classGen, this.collection); + } else { + Configuration.getObfuscationOptions(); + if (value == 2) { + StringEncryptionUtils.processClassGen2(classGen); + } else { + Configuration.getObfuscationOptions(); + if (value == 3) { + StringEncryptionUtils.processClassGen2(classGen); + StringEncryptionUtils.processClassGen(classGen); + } + } + } + byte value3 = 0; + if (this.matchesClassGen2(classGen)) { + Vector vector; + if ((vector = (Vector) this.entries7.get(this.getText(classGen))) == null) { + vector = new Vector(); + this.entries7.put(this.getText(classGen), vector); + if (this.entries4.get(this.getText(classGen)) == null) { + Vector vector2 = new Vector(); + if (this.classStorage.matchesClassGen(classGen) + && !classGen.isEnabled2() + && !classGen.isEnabled5()) { + vector2.add(classGen); + value3 = 1; + } + this.entries4.put(this.getText(classGen), vector2); + } + } + if (!this.classStorage.matchesClassGen(classGen) + || !classGen.isEnabled2() && !classGen.isEnabled5()) { + vector.add(classGen); + } + } + if (value3 == 0 && this.matchesClassGen(classGen)) { + Vector vector3; + if ((vector3 = (Vector) this.entries4.get(this.getText(classGen))) == null) { + vector3 = new Vector(); + this.entries4.put(this.getText(classGen), vector3); + } + vector3.add(classGen); + } + continue label133; + } + } + Iterator iterator3; + Iterator iterator4 = iterator3 = this.entries4.values().iterator(); + while (iterator4.hasNext()) { + Vector vector4 = (Vector) iterator3.next(); + iterator4 = iterator3; + this.processValues(vector4); + } + Vector vector5 = new Vector(); + Iterator iterator5 = this.entries4.values().iterator(); + while (iterator5.hasNext()) { + Vector vector6; + if ((vector6 = (Vector) iterator5.next()).size() > vector5.size()) { + vector5 = vector6; + } + } + if (vector5.size() == 0) { + this.enabled = false; + return; + } + String text = this.getText((ClassGen) vector5.get(0)); + HashSet values2; + (values2 = new HashSet()).addAll(this.entries4.keySet()); + for (String text2 : ((Iterable) ((Iterable) values2))) { + if (((Vector) this.entries4.get(text2)).size() == 0) { + if (this.matchesBoolean((Boolean) this.entries8.get(text2))) { + this.entries8.put(text, true); + } + if (this.matchesBoolean((Boolean) this.entries2.get(text2))) { + this.entries2.put(text, true); + } + } + } + Iterator iterator6; + iterator4 = iterator6 = this.entries4.values().iterator(); + while (iterator4.hasNext()) { + Vector vector7 = (Vector) iterator6.next(); + iterator4 = iterator6; + this.processValues2(vector7); + } + values2.clear(); + values2.addAll(this.entries3.keySet()); + values2.addAll(this.entries5.keySet()); + Iterator iterator7 = values2.iterator(); + for (Iterator iterator8 = iterator7; iterator8.hasNext(); iterator8 = iterator7) { + String text3 = (String) iterator7.next(); + this.processValues((Vector) this.entries3.get(text3), (Vector) this.entries5.get(text3)); + } + values2.clear(); + values2.addAll(this.entries4.keySet()); + for (String text4 : ((Iterable) ((Iterable) values2))) { + if (((Vector) this.entries4.get(text4)).size() == 0) { + this.entries4.put(text4, vector5); + this.entries3.put(text4, this.entries3.get(text)); + this.entries5.put(text4, this.entries5.get(text)); + } + } + return; + } + } + + public String getText(ClassGen classGen) { + if (Configuration.getObfuscationOptions().isPackageStringEncryptionEnabled()) { + String text; + return (text = classGen.getClassName()).indexOf(46) > 0 + ? text.substring(0, text.lastIndexOf(46)) + : ""; + } + if (classGen.getClassName().startsWith(this.text6)) { + return "SPRINGBOOT"; + } + if (Configuration.getObfuscationOptions().isGlobalStringEncryptionEnabled()) { + return "GLOBAL"; + } + if (!this.classStorage.matchesClassGen(classGen)) { + return this.classStorage.getText(classGen); + } + String text2; + if ((text2 = classGen.getClassName()).indexOf(36) > 0) { + text2 = text2.substring(0, text2.indexOf(36)); + } + return text2; + } + + public String createText(String text, String text2) { + char[] values = new char[text.length()]; + char value = (char) ((int[]) this.entries.get(text2))[0]; + char value2 = (char) ((int[]) this.entries.get(text2))[1]; + int value3; + for (int value4 = value3 = values.length - 1; value4 >= 0; value4 = value3) { + char value5 = (char) (text.charAt(value3) ^ value); + int value6 = value3; + value3--; + values[value6] = value5; + if (value3 < 0) { + break; + } + char value7 = (char) (text.charAt(value3) ^ value2); + int value8 = value3; + value3--; + values[value8] = value7; + } + return new String(values); + } +} diff --git a/src/main/java/com/allatori/transform/FieldAccessTransformer.java b/src/main/java/com/allatori/transform/FieldAccessTransformer.java new file mode 100644 index 0000000..59cfc08 --- /dev/null +++ b/src/main/java/com/allatori/transform/FieldAccessTransformer.java @@ -0,0 +1,91 @@ +package com.allatori.transform; + +import com.allatori.bytecode.MethodFactory; +import com.allatori.config.Configuration; +import com.allatori.lib.bcel.classfile.Method; +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.lib.bcel.generic.InstructionFactory; +import com.allatori.lib.bcel.generic.InstructionHandle; +import com.allatori.lib.bcel.generic.InstructionList; +import com.allatori.lib.bcel.generic.InstructionTargeter; +import com.allatori.lib.bcel.generic.MethodGen; +import com.allatori.lib.bcel.generic.Type; +import com.allatori.model.ClassStorage; + +public class FieldAccessTransformer implements ClassTransformer { + + public ClassStorage classStorage; + + @Override + public void finish() {} + + @Override + public void transform(ClassGen classGen) { + String text2 = Configuration.getDebugInfoOptions().getText2(); + String text = Configuration.getDebugInfoOptions().getText(); + if (text2 != null && text != null) { + if (Configuration.getDebugInfoOptions().matchesClassGen(this.classStorage, classGen)) { + try { + Method[] methods = classGen.getMethods(); + for (int index = 0; index < methods.length; index++) { + Method method; + if ((method = methods[index]).getCode() != null) { + MethodGen methodGen = + MethodFactory.createMethodGen( + method, + classGen.getClassName(), + classGen.getConstantPool(), + classGen.getConstantPool().getConstantPool()); + if (Configuration.getDebugInfoOptions() + .matchesMethodGen(this.classStorage, classGen, methodGen)) { + InstructionFactory instructionFactory = new InstructionFactory(classGen); + InstructionList instructionList; + InstructionHandle end = (instructionList = methodGen.getInstructionList()).getEnd(); + InstructionHandle instructionHandle; + InstructionHandle instructionHandle2; + if (Configuration.getDebugInfoOptions().isEnabled()) { + InstructionHandle instructionHandle3 = + instructionList.createInstructionHandle( + end, + instructionFactory.createInvoke( + text2, text, Type.VOID, new Type[] {Type.OBJECT}, (short) 184)); + instructionHandle = + instructionList.createInstructionHandle( + instructionHandle3, InstructionFactory.createThis()); + instructionHandle2 = end; + } else { + instructionHandle = + instructionList.createInstructionHandle( + end, + instructionFactory.createInvoke( + text2, text, Type.VOID, Type.NO_ARGS, (short) 184)); + instructionHandle2 = end; + } + InstructionTargeter[] instructionTargeters; + int value; + for (int value2 = + value = + (instructionTargeters = instructionHandle2.getTargeters()).length - 1; + value2 >= 0; + value2 = value) { + InstructionTargeter instructionTargeter = instructionTargeters[value]; + value--; + instructionTargeter.updateTarget(end, instructionHandle); + } + methodGen.update5(); + classGen.replaceMethod(method, methodGen.getMethod()); + } + } + } + } catch (Exception exception) { + exception.printStackTrace(); + } + } + } + } + + public FieldAccessTransformer(ClassStorage classStorage2) { + super(); + this.classStorage = classStorage2; + } +} diff --git a/src/main/java/com/allatori/transform/FieldOrderComparator.java b/src/main/java/com/allatori/transform/FieldOrderComparator.java new file mode 100644 index 0000000..2ab14e6 --- /dev/null +++ b/src/main/java/com/allatori/transform/FieldOrderComparator.java @@ -0,0 +1,31 @@ +package com.allatori.transform; + +import com.allatori.config.Configuration; +import com.allatori.lib.bcel.classfile.Field; +import java.util.Comparator; + +public class FieldOrderComparator implements Comparator { + + public final int count; + + public final MemberReorderTransformer memberReorderTransformer; + + @Override + public int compare(Object result, Object result2) { + return this.calculateCount((Field) result, (Field) result2); + } + + public int calculateCount(Field field, Field field2) { + int value = this.count; + Configuration.getObfuscationOptions(); + return value == 100 + ? field2.getText().compareTo(field.getText()) + : field.getText().compareTo(field2.getText()); + } + + public FieldOrderComparator(MemberReorderTransformer memberReorderTransformer2, int count) { + super(); + this.memberReorderTransformer = memberReorderTransformer2; + this.count = count; + } +} diff --git a/src/main/java/com/allatori/transform/GlobalStringEncryptionTransformer.java b/src/main/java/com/allatori/transform/GlobalStringEncryptionTransformer.java new file mode 100644 index 0000000..7190c91 --- /dev/null +++ b/src/main/java/com/allatori/transform/GlobalStringEncryptionTransformer.java @@ -0,0 +1,611 @@ +package com.allatori.transform; + +import com.allatori.bytecode.ConstantPoolEditor; +import com.allatori.bytecode.MethodFactory; +import com.allatori.config.Configuration; +import com.allatori.crypto.CustomStringEncryption; +import com.allatori.crypto.StringEncryptionUtils; +import com.allatori.internal.NameSignatureInstructionSupport; +import com.allatori.lib.bcel.classfile.Constant; +import com.allatori.lib.bcel.classfile.ConstantString; +import com.allatori.lib.bcel.classfile.ConstantUtf8; +import com.allatori.lib.bcel.classfile.Method; +import com.allatori.lib.bcel.generic.ArrayType; +import com.allatori.lib.bcel.generic.BranchHandle; +import com.allatori.lib.bcel.generic.BranchInstruction; +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.lib.bcel.generic.ConstantPoolGen; +import com.allatori.lib.bcel.generic.IINC; +import com.allatori.lib.bcel.generic.Instruction; +import com.allatori.lib.bcel.generic.InstructionConstants; +import com.allatori.lib.bcel.generic.InstructionFactory; +import com.allatori.lib.bcel.generic.InstructionHandle; +import com.allatori.lib.bcel.generic.InstructionList; +import com.allatori.lib.bcel.generic.LDC; +import com.allatori.lib.bcel.generic.MethodGen; +import com.allatori.lib.bcel.generic.ObjectType; +import com.allatori.lib.bcel.generic.PUSH; +import com.allatori.lib.bcel.generic.Type; +import com.allatori.model.ClassStorage; +import com.allatori.util.Log; +import java.util.Collection; +import java.util.Iterator; +import java.util.TreeSet; +import java.util.Vector; + +public class GlobalStringEncryptionTransformer implements ClassTransformer { + + public static String text2 = "com_allatori_string_decryptor"; + + public static String text5 = "DecryptString"; + + public static String text = "DecryptString2"; + + public static String text4 = "allatori-12321-32123:"; + + public static char character = 'U'; + + public static boolean enabled = false; + + public static String text3 = "makeConcatWithConstants"; + + public Collection collection; + + public ClassStorage classStorage; + + public static Vector values; + + public boolean enabled2 = false; + + @Override + public void finish() { + if (this.enabled2) { + this.classStorage.processClassGen(this.createClassGen()); + } + } + + public void transform2(ClassGen classGen) { + InstructionFactory instructionFactory = new InstructionFactory(classGen); + ConstantPoolGen constantPool = classGen.getConstantPool(); + InstructionList instructionList = new InstructionList(); + MethodGen methodGen = + new MethodGen( + 9, + Type.STRING, + new Type[] {Type.STRING}, + new String[] {"s"}, + text5, + classGen.getClassName(), + instructionList, + constantPool); + instructionList.getInstructionHandle(instructionFactory.createNew("java.lang.String")); + instructionList.getInstructionHandle(InstructionConstants.DUP); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.OBJECT, 0)); + instructionList.getInstructionHandle( + instructionFactory.createInvoke( + "java.lang.String", "length", Type.INT, Type.NO_ARGS, (short) 182)); + instructionList.getInstructionHandle(instructionFactory.createNewArray(Type.CHAR, (short) 1)); + instructionList.getInstructionHandle(new PUSH(constantPool, 1)); + instructionList.getInstructionHandle(InstructionConstants.DUP); + instructionList.getInstructionHandle(InstructionConstants.POP2); + Iterator iterator2 = StringEncryptionUtils.createValues(character).iterator(); + Iterator iterator3 = iterator2; + while (iterator3.hasNext()) { + Instruction instruction = (Instruction) iterator2.next(); + iterator3 = iterator2; + instructionList.getInstructionHandle(instruction); + } + instructionList.getInstructionHandle(InstructionConstants.SWAP); + instructionList.getInstructionHandle(InstructionConstants.DUP); + instructionList.getInstructionHandle(InstructionConstants.ARRAYLENGTH); + instructionList.getInstructionHandle(new PUSH(constantPool, 1)); + instructionList.getInstructionHandle(InstructionConstants.ISUB); + instructionList.getInstructionHandle(InstructionConstants.DUP_X2); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction(Type.INT, 3)); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction(Type.OBJECT, 1)); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction(Type.INT, 2)); + BranchInstruction branchInstruction = + InstructionFactory.createBranchInstruction((short) 155, null); + BranchHandle branchHandle = instructionList.getBranchHandle(branchInstruction); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.OBJECT, 1)); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.INT, 3)); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.OBJECT, 0)); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.INT, 3)); + instructionList.getInstructionHandle( + instructionFactory.createInvoke( + "java.lang.String", "charAt", Type.CHAR, new Type[] {Type.INT}, (short) 182)); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.INT, 2)); + instructionList.getInstructionHandle(InstructionConstants.IXOR); + instructionList.getInstructionHandle(InstructionConstants.I2C); + instructionList.getInstructionHandle(InstructionConstants.SWAP); + instructionList.getInstructionHandle(InstructionConstants.DUP_X1); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.INT, 2)); + instructionList.getInstructionHandle(InstructionConstants.IXOR); + instructionList.getInstructionHandle(InstructionConstants.I2C); + instructionList.getInstructionHandle(new PUSH(constantPool, 63)); + instructionList.getInstructionHandle(InstructionConstants.IAND); + instructionList.getInstructionHandle(InstructionConstants.I2C); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction(Type.INT, 2)); + instructionList.getInstructionHandle(InstructionConstants.CASTORE); + instructionList.getInstructionHandle(new IINC(3, -1)); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.INT, 3)); + BranchInstruction branchInstruction2 = + InstructionFactory.createBranchInstruction((short) 155, null); + instructionList.getBranchHandle(branchInstruction2); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.OBJECT, 1)); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.INT, 3)); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.OBJECT, 0)); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.INT, 3)); + instructionList.getInstructionHandle( + instructionFactory.createInvoke( + "java.lang.String", "charAt", Type.CHAR, new Type[] {Type.INT}, (short) 182)); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.INT, 2)); + instructionList.getInstructionHandle(InstructionConstants.IXOR); + instructionList.getInstructionHandle(InstructionConstants.I2C); + instructionList.getInstructionHandle(InstructionConstants.SWAP); + instructionList.getInstructionHandle(InstructionConstants.DUP_X1); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.INT, 2)); + instructionList.getInstructionHandle(InstructionConstants.IXOR); + instructionList.getInstructionHandle(InstructionConstants.I2C); + instructionList.getInstructionHandle(new PUSH(constantPool, 63)); + instructionList.getInstructionHandle(InstructionConstants.IAND); + instructionList.getInstructionHandle(InstructionConstants.I2C); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction(Type.INT, 2)); + instructionList.getInstructionHandle(InstructionConstants.CASTORE); + instructionList.getInstructionHandle(new IINC(3, -1)); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.INT, 3)); + instructionList.getBranchHandle( + InstructionFactory.createBranchInstruction((short) 167, branchHandle)); + InstructionHandle instructionHandle = + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.OBJECT, 1)); + instructionList.getInstructionHandle( + instructionFactory.createInvoke( + "java.lang.String", + "", + Type.VOID, + new Type[] {new ArrayType(Type.CHAR, 1)}, + (short) 183)); + instructionList.getInstructionHandle(InstructionFactory.createReturn(Type.OBJECT)); + branchInstruction.setTarget(instructionHandle); + branchInstruction2.setTarget(instructionHandle); + methodGen.update5(); + methodGen.update4(); + classGen.processMethod2(methodGen.getMethod()); + instructionList.update3(); + } + + @Override + public void transform(ClassGen classGen) { + InstructionHandle instructionHandle; + int value = Configuration.getObfuscationOptions().calculateCount(this.classStorage, classGen); + Configuration.getObfuscationOptions(); + if (value != 0) { + InstructionFactory instructionFactory = new InstructionFactory(classGen); + Method[] methods = classGen.getMethods(); + int value2; + for (value = value2 = 0; value < methods.length; value = ++value2) { + Method method; + if ((method = methods[value2]).getCode() != null) { + if (classGen.getConstantPool().getSize() > 20000) { + new ConstantPoolEditor(this.classStorage).processClassGen(classGen); + instructionFactory = new InstructionFactory(classGen); + method = (methods = classGen.getMethods())[value2]; + } + InstructionHandle instructionHandle2; + InstructionList instructionList; + MethodGen methodGen; + InstructionHandle instructionHandle3 = + instructionHandle2 = + (instructionList = + (methodGen = + MethodFactory.createMethodGen( + method, + classGen.getClassName(), + classGen.getConstantPool(), + classGen.getConstantPool().getConstantPool())) + .getInstructionList()) + .getStart(); + while (instructionHandle3 != null) { + label111: + { + if (!enabled + && instructionHandle2.getInstruction() + instanceof NameSignatureInstructionSupport) { + NameSignatureInstructionSupport nameSignatureInstructionSupport = + (NameSignatureInstructionSupport) instructionHandle2.getInstruction(); + if (text3.equals( + nameSignatureInstructionSupport.getText3(classGen.getConstantPool()))) { + Log.warn( + "javac Java compiler should be run with -XDstringConcat=inline flag to" + + " encrypt all strings."); + enabled = true; + } + } else if (instructionHandle2.getInstruction() instanceof LDC) { + LDC lDC = (LDC) instructionHandle2.getInstruction(); + Constant constant; + if ((constant = classGen.getConstantPool().getConstant(lDC.getIndex())) + instanceof ConstantString) { + String bytes = + ((ConstantUtf8) + classGen + .getConstantPool() + .getConstant(((ConstantString) constant).getStringIndex())) + .getBytes(); + if (this.classStorage.getClassGen(bytes) != null + || this.collection.contains(bytes) + || StringEncryptionUtils.matchesText(bytes)) { + instructionHandle3 = + instructionHandle2 = instructionHandle2.getInstructionHandle2(); + continue; + } + int value3; + label85: + { + value3 = + Configuration.getObfuscationOptions() + .calculateCount(this.classStorage, classGen, methodGen); + String text6; + if ((text6 = classGen.getClassName()).startsWith((String) "com.allatori")) { + if (text6.startsWith("com.allatori.obfuscate.opt")) { + Configuration.getObfuscationOptions(); + value3 = 0; + } + if (text6.startsWith("com.allatori.obfuscate.ren")) { + Configuration.getObfuscationOptions(); + value3 = 0; + } + if (text6.startsWith("com.allatori.io.re")) { + Configuration.getObfuscationOptions(); + value3 = 0; + value = value3; + break label85; + } + } else if (text6.startsWith((String) "org.apache.bcel")) { + Configuration.getObfuscationOptions(); + value3 = 0; + } + value = value3; + } + Configuration.getObfuscationOptions(); + if (value == 1) { + lDC.setIndex(classGen.getConstantPool().addString("" + text4 + bytes)); + instructionList.createInstructionHandle2( + instructionHandle2, + instructionFactory.createInvoke( + text2, text, Type.STRING, new Type[] {Type.STRING}, (short) 184)); + if (!values.contains(classGen)) { + values.add(classGen); + } + this.enabled2 = true; + instructionHandle = instructionHandle2; + break label111; + } + Configuration.getObfuscationOptions(); + if (value3 >= 1000) { + String text7; + if ((text7 = + CustomStringEncryption.createText( + bytes, value3, this.classStorage.getClassLoader())) + .startsWith(CustomStringEncryption.text) + && !values.contains(classGen)) { + values.add(classGen); + } + lDC.setIndex(classGen.getConstantPool().addString(text7)); + instructionHandle = instructionHandle2; + instructionList.createInstructionHandle2( + instructionHandle2, + CustomStringEncryption.getInvokeInstruction(instructionFactory, value3)); + break label111; + } + lDC.setIndex(classGen.getConstantPool().addString(this.createText(bytes))); + instructionList.createInstructionHandle2( + instructionHandle2, + instructionFactory.createInvoke( + text2, text5, Type.STRING, new Type[] {Type.STRING}, (short) 184)); + this.enabled2 = true; + } + } + instructionHandle = instructionHandle2; + } + instructionHandle3 = instructionHandle2 = instructionHandle.getInstructionHandle2(); + } + methodGen.update5(); + classGen.replaceMethod(method, methodGen.getMethod()); + } + } + } + } + + public GlobalStringEncryptionTransformer(ClassStorage classStorage2) { + this.collection = new TreeSet(); + this.classStorage = classStorage2; + character = Configuration.getObfuscationOptions().getCharacter(); + values = new Vector(); + StringEncryptionUtils.update(); + this.collection.add(""); + Iterator classesByName2 = classStorage2.getClassesByName2(); + label27: + while (true) { + for (Iterator iterator = classesByName2; iterator.hasNext(); iterator = classesByName2) { + ClassGen classGen = (ClassGen) classesByName2.next(); + if (!Configuration.getIgnoreClassesOptions().matchesClassGen(classStorage2, classGen)) { + int value; + int value2 = + value = Configuration.getObfuscationOptions().calculateCount(classStorage2, classGen); + Configuration.getObfuscationOptions(); + if (value2 == 1) { + StringEncryptionUtils.processCollection(classGen, this.collection); + } else { + Configuration.getObfuscationOptions(); + if (value == 2) { + StringEncryptionUtils.processClassGen2(classGen); + } else { + Configuration.getObfuscationOptions(); + if (value == 3) { + StringEncryptionUtils.processClassGen2(classGen); + StringEncryptionUtils.processClassGen(classGen); + } + } + } + continue label27; + } + } + return; + } + } + + public String createText(String text) { + char[] values = new char[text.length()]; + char value = character; + int value2; + for (int value3 = value2 = values.length - 1; value3 >= 0; value3 = value2) { + values[value2] = (char) (text.charAt(value2) ^ value); + char value4 = (char) (value ^ value2); + value2--; + value = (char) (value4 & (byte) 63); + } + return new String(values); + } + + public void transform3(ClassGen classGen) { + InstructionFactory instructionFactory = new InstructionFactory(classGen); + ConstantPoolGen constantPool = classGen.getConstantPool(); + InstructionList instructionList = new InstructionList(); + MethodGen methodGen = + new MethodGen( + 9, + Type.STRING, + new Type[] {Type.STRING}, + new String[] {"arg0"}, + text, + classGen.getClassName(), + instructionList, + constantPool); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.OBJECT, 0)); + instructionList.getInstructionHandle(new PUSH(constantPool, 1)); + instructionList.getInstructionHandle(InstructionConstants.DUP); + instructionList.getInstructionHandle(InstructionConstants.DUP_X2); + String text2 = "java.lang.RuntimeException"; + instructionList.getInstructionHandle(instructionFactory.createNew(text2)); + instructionList.getInstructionHandle(InstructionConstants.DUP); + instructionList.getInstructionHandle( + instructionFactory.createInvoke(text2, "", Type.VOID, Type.NO_ARGS, (short) 183)); + instructionList.getInstructionHandle( + instructionFactory.createInvoke( + text2, + "getStackTrace", + new ArrayType(new ObjectType("java.lang.StackTraceElement"), 1), + Type.NO_ARGS, + (short) 182)); + instructionList.getInstructionHandle(InstructionConstants.SWAP); + instructionList.getInstructionHandle(InstructionConstants.AALOAD); + instructionList.getInstructionHandle(instructionFactory.createNew("java.lang.StringBuffer")); + instructionList.getInstructionHandle(InstructionConstants.DUP); + instructionList.getInstructionHandle( + instructionFactory.createInvoke( + "java.lang.StringBuffer", "", Type.VOID, Type.NO_ARGS, (short) 183)); + instructionList.getInstructionHandle(InstructionConstants.SWAP); + instructionList.getInstructionHandle(InstructionConstants.DUP); + instructionList.getInstructionHandle( + instructionFactory.createInvoke( + "java.lang.StackTraceElement", "getClassName", Type.STRING, Type.NO_ARGS, (short) 182)); + instructionList.getInstructionHandle(InstructionConstants.SWAP); + instructionList.getInstructionHandle( + instructionFactory.createInvoke( + "java.lang.StackTraceElement", + "getMethodName", + Type.STRING, + Type.NO_ARGS, + (short) 182)); + instructionList.getInstructionHandle(InstructionConstants.DUP_X2); + instructionList.getInstructionHandle(InstructionConstants.POP); + instructionList.getInstructionHandle( + instructionFactory.createInvoke( + "java.lang.StringBuffer", + "append", + Type.STRINGBUFFER, + new Type[] {Type.STRING}, + (short) 182)); + instructionList.getInstructionHandle(InstructionConstants.SWAP); + instructionList.getInstructionHandle( + instructionFactory.createInvoke( + "java.lang.StringBuffer", + "append", + Type.STRINGBUFFER, + new Type[] {Type.STRING}, + (short) 182)); + instructionList.getInstructionHandle( + instructionFactory.createInvoke( + "java.lang.StringBuffer", "toString", Type.STRING, Type.NO_ARGS, (short) 182)); + instructionList.getInstructionHandle(InstructionConstants.DUP_X1); + instructionList.getInstructionHandle( + instructionFactory.createInvoke( + "java.lang.String", "length", Type.INT, Type.NO_ARGS, (short) 182)); + instructionList.getInstructionHandle(InstructionConstants.SWAP); + instructionList.getInstructionHandle(InstructionConstants.ISUB); + instructionList.getInstructionHandle(InstructionConstants.DUP_X1); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction(Type.INT, 3)); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction(Type.OBJECT, 2)); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction(Type.INT, 4)); + instructionList.getInstructionHandle( + instructionFactory.createInvoke( + "java.lang.String", "length", Type.INT, Type.NO_ARGS, (short) 182)); + instructionList.getInstructionHandle(InstructionConstants.DUP); + instructionList.getInstructionHandle(instructionFactory.createNewArray(Type.CHAR, (short) 1)); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction(Type.OBJECT, 5)); + Iterator iterator2 = StringEncryptionUtils.createValues(character).iterator(); + Iterator iterator3 = iterator2; + while (iterator3.hasNext()) { + Instruction instruction = (Instruction) iterator2.next(); + iterator3 = iterator2; + instructionList.getInstructionHandle(instruction); + } + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction(Type.INT, 6)); + instructionList.getInstructionHandle(InstructionConstants.SWAP); + instructionList.getInstructionHandle(InstructionConstants.ISUB); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction(Type.INT, 7)); + BranchInstruction branchInstruction = + InstructionFactory.createBranchInstruction((short) 167, null); + instructionList.getBranchHandle(branchInstruction); + InstructionHandle instructionHandle = + instructionList.getInstructionHandle(new PUSH(constantPool, 63)); + instructionList.getInstructionHandle(InstructionConstants.DUP_X2); + instructionList.getInstructionHandle(InstructionConstants.POP); + instructionList.getInstructionHandle(InstructionConstants.DUP_X1); + instructionList.getInstructionHandle(InstructionConstants.POP); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.INT, 6)); + instructionList.getInstructionHandle(InstructionConstants.DUP_X2); + instructionList.getInstructionHandle(InstructionConstants.POP); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.OBJECT, 2)); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.INT, 4)); + instructionList.getInstructionHandle( + instructionFactory.createInvoke( + "java.lang.String", "charAt", Type.CHAR, new Type[] {Type.INT}, (short) 182)); + instructionList.getInstructionHandle(InstructionConstants.DUP_X1); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.INT, 7)); + instructionList.getInstructionHandle(InstructionConstants.DUP_X1); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.OBJECT, 0)); + instructionList.getInstructionHandle(InstructionConstants.SWAP); + instructionList.getInstructionHandle( + instructionFactory.createInvoke( + "java.lang.String", "charAt", Type.CHAR, new Type[] {Type.INT}, (short) 182)); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.INT, 6)); + instructionList.getInstructionHandle(InstructionConstants.IXOR); + instructionList.getInstructionHandle(InstructionConstants.IXOR); + instructionList.getInstructionHandle(InstructionConstants.I2C); + instructionList.getInstructionHandle(InstructionConstants.CASTORE); + instructionList.getInstructionHandle(InstructionConstants.IXOR); + instructionList.getInstructionHandle(InstructionConstants.IXOR); + instructionList.getInstructionHandle(InstructionConstants.IAND); + instructionList.getInstructionHandle(InstructionConstants.I2C); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction(Type.INT, 6)); + instructionList.getInstructionHandle(new IINC(4, -1)); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.INT, 4)); + BranchInstruction branchInstruction2 = + InstructionFactory.createBranchInstruction((short) 156, null); + instructionList.getBranchHandle(branchInstruction2); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.INT, 3)); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction(Type.INT, 4)); + InstructionHandle instructionHandle2 = instructionList.getInstructionHandle(new IINC(7, -1)); + InstructionHandle instructionHandle3 = + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.OBJECT, 5)); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.INT, 7)); + instructionList.getInstructionHandle(InstructionConstants.DUP); + BranchInstruction branchInstruction3 = + InstructionFactory.createBranchInstruction((short) 156, instructionHandle); + instructionList.getBranchHandle(branchInstruction3); + instructionList.getInstructionHandle(InstructionConstants.POP2); + instructionList.getInstructionHandle(instructionFactory.createNew("java.lang.String")); + instructionList.getInstructionHandle( + InstructionFactory.createLocalVariableInstruction2(Type.OBJECT, 5)); + instructionList.getInstructionHandle(InstructionConstants.SWAP); + instructionList.getInstructionHandle(InstructionConstants.DUP_X1); + instructionList.getInstructionHandle(InstructionConstants.SWAP); + instructionList.getInstructionHandle( + instructionFactory.createInvoke( + "java.lang.String", + "", + Type.VOID, + new Type[] {new ArrayType(Type.CHAR, 1)}, + (short) 183)); + instructionList.getInstructionHandle(InstructionFactory.createReturn(Type.OBJECT)); + branchInstruction.setTarget(instructionHandle3); + branchInstruction2.setTarget(instructionHandle2); + methodGen.update5(); + methodGen.update4(); + classGen.processMethod2(methodGen.getMethod()); + instructionList.update3(); + } + + public void finish2() {} + + public static String createText(String text, String text2) { + int value = text2.length() - 1; + int value2 = text2.length() - 1; + char[] values = new char[text.length()]; + char value3 = character; + int value4; + for (int value5 = value4 = values.length - 1; value5 >= 0; value5 = --value4) { + values[value4] = (char) (text.charAt(value4) ^ value3 ^ text2.charAt(value2)); + char value6 = (char) (value3 ^ value4 ^ text2.charAt(value2)); + value2--; + value3 = (char) (value6 & (byte) 63); + if (value2 < 0) { + value2 = value; + } + } + return new String(values); + } + + public ClassGen createClassGen() { + ClassGen classGen = new ClassGen(text2, "java.lang.Object", "", 33, new String[0]); + if (Configuration.getObfuscationOptions().isEnabled()) { + StringEncryptionUtils.processCharacter(classGen, text5, character); + return classGen; + } else { + this.transform2(classGen); + this.transform3(classGen); + return classGen; + } + } +} diff --git a/src/main/java/com/allatori/transform/HardwareIdTransformer.java b/src/main/java/com/allatori/transform/HardwareIdTransformer.java new file mode 100644 index 0000000..6b12421 --- /dev/null +++ b/src/main/java/com/allatori/transform/HardwareIdTransformer.java @@ -0,0 +1,35 @@ +package com.allatori.transform; + +import com.allatori.config.Configuration; +import com.allatori.lib.bcel.classfile.ConstantUtf8; +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.model.ClassStorage; + +public class HardwareIdTransformer implements ClassTransformer { + + public ClassStorage classStorage; + + @Override + public void transform(ClassGen classGen) { + try { + int value; + ClassGen classGen2; + if ((classGen2 = this.classStorage.getClassGen("com.license4j.HardwareID")) != null + && (value = classGen2.getConstantPool().lookupUtf8("resources/d.bfi")) != -1) { + ((ConstantUtf8) classGen2.getConstantPool().getConstant(value)) + .setBytes(Configuration.getLogOptions().getComLicense4jSupport()); + return; + } + } catch (Exception exception) { + exception.printStackTrace(); + } + } + + public HardwareIdTransformer(ClassStorage classStorage2) { + super(); + this.classStorage = classStorage2; + } + + @Override + public void finish() {} +} diff --git a/src/main/java/com/allatori/transform/MemberConstantPoolTransformer.java b/src/main/java/com/allatori/transform/MemberConstantPoolTransformer.java new file mode 100644 index 0000000..878e602 --- /dev/null +++ b/src/main/java/com/allatori/transform/MemberConstantPoolTransformer.java @@ -0,0 +1,112 @@ +package com.allatori.transform; + +import com.allatori.bytecode.ConstantPoolEditor; +import com.allatori.bytecode.MethodFactory; +import com.allatori.crypto.CustomStringEncryption; +import com.allatori.lib.bcel.classfile.Constant; +import com.allatori.lib.bcel.classfile.ConstantString; +import com.allatori.lib.bcel.classfile.ConstantUtf8; +import com.allatori.lib.bcel.classfile.Method; +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.lib.bcel.generic.InstructionHandle; +import com.allatori.lib.bcel.generic.LDC; +import com.allatori.lib.bcel.generic.MethodGen; +import com.allatori.model.ClassStorage; + +public class MemberConstantPoolTransformer implements ClassTransformer { + + public ConstantPoolEditor constantPoolEditor; + + public ClassStorage classStorage; + + public void transform2(ClassGen classGen) { + InstructionHandle instructionHandle; + Method[] methods = classGen.getMethods(); + int value; + for (int value2 = value = 0; value2 < methods.length; value2 = ++value) { + Method method; + if ((method = methods[value]).getCode() != null) { + MethodGen methodGen; + InstructionHandle instructionHandle2; + InstructionHandle instructionHandle3 = + instructionHandle2 = + (methodGen = + MethodFactory.createMethodGen( + method, + classGen.getClassName(), + classGen.getConstantPool(), + classGen.getConstantPool().getConstantPool())) + .getInstructionList() + .getStart(); + while (instructionHandle3 != null) { + label38: + { + if (instructionHandle2.getInstruction() instanceof LDC) { + LDC lDC = (LDC) instructionHandle2.getInstruction(); + Constant constant; + if ((constant = classGen.getConstantPool().getConstant(lDC.getIndex())) + instanceof ConstantString) { + String text2; + if ((text2 = + ((ConstantUtf8) + classGen + .getConstantPool() + .getConstant(((ConstantString) constant).getStringIndex())) + .getBytes()) + != null + && text2.startsWith(GlobalStringEncryptionTransformer.text4)) { + String text3 = text2.substring(GlobalStringEncryptionTransformer.text4.length()); + String text5 = "" + classGen.getClassName() + methodGen.getName(); + instructionHandle = instructionHandle2; + lDC.setIndex( + classGen + .getConstantPool() + .addString(GlobalStringEncryptionTransformer.createText(text3, text5))); + break label38; + } + if (text2 != null && text2.startsWith(CustomStringEncryption.text)) { + lDC.setIndex( + classGen + .getConstantPool() + .addString( + CustomStringEncryption.createText( + text2, + this.classStorage.getClassLoader(), + classGen.getClassName(), + methodGen.getName()))); + } + } + } + instructionHandle = instructionHandle2; + } + instructionHandle3 = instructionHandle2 = instructionHandle.getInstructionHandle2(); + } + methodGen.update5(); + classGen.replaceMethod(method, methodGen.getMethod()); + } + } + } + + @Override + public void transform(ClassGen classGen) { + if (GlobalStringEncryptionTransformer.values.contains(classGen)) { + try { + this.transform2(classGen); + } catch (Exception exception) { + this.constantPoolEditor.processClassGen(classGen); + this.transform2(classGen); + } + } + } + + @Override + public void finish() { + GlobalStringEncryptionTransformer.values = null; + } + + public MemberConstantPoolTransformer(ClassStorage classStorage2) { + super(); + this.constantPoolEditor = new ConstantPoolEditor(null); + this.classStorage = classStorage2; + } +} diff --git a/src/main/java/com/allatori/transform/MemberReorderTransformer.java b/src/main/java/com/allatori/transform/MemberReorderTransformer.java new file mode 100644 index 0000000..2a4628a --- /dev/null +++ b/src/main/java/com/allatori/transform/MemberReorderTransformer.java @@ -0,0 +1,169 @@ +package com.allatori.transform; + +import com.allatori.config.Configuration; +import com.allatori.lib.bcel.classfile.Field; +import com.allatori.lib.bcel.classfile.Method; +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.model.ClassStorage; +import com.allatori.util.random.RandomUtils; +import java.util.Arrays; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Vector; + +public class MemberReorderTransformer implements ClassTransformer { + + public ClassStorage classStorage; + + public Vector values; + + public Vector values2; + + @Override + public void transform(ClassGen classGen) { + int value; + int value2 = + value = Configuration.getObfuscationOptions().calculateCount2(this.classStorage, classGen); + Configuration.getObfuscationOptions(); + if (value2 == 100) { + this.values.add(classGen); + } else { + Configuration.getObfuscationOptions(); + if (value == 101) { + this.values2.add(classGen); + } else { + this.processCount(classGen, value); + this.processCount2(classGen, value); + } + } + } + + @Override + public void finish() { + Iterator iterator2; + Iterator iterator3 = iterator2 = this.values.iterator(); + while (iterator3.hasNext()) { + ClassGen classGen = (ClassGen) iterator2.next(); + iterator3 = iterator2; + Configuration.getObfuscationOptions(); + this.processCount(classGen, 100); + Configuration.getObfuscationOptions(); + this.processCount2(classGen, 100); + } + Iterator iterator4; + iterator3 = iterator4 = this.values2.iterator(); + while (iterator3.hasNext()) { + ClassGen classGen2 = (ClassGen) iterator4.next(); + iterator3 = iterator4; + Configuration.getObfuscationOptions(); + this.processCount(classGen2, 101); + Configuration.getObfuscationOptions(); + this.processCount2(classGen2, 101); + } + this.values2 = this.values = null; + } + + public MemberReorderTransformer(ClassStorage classStorage2) { + super(); + this.classStorage = classStorage2; + this.values = new Vector(); + this.values2 = new Vector(); + } + + public void processCount(ClassGen classGen, int value) { + Configuration.getObfuscationOptions(); + if (value == 1) { + int value2; + Field[] fields; + for (int value3 = value2 = (fields = classGen.getFields()).length - 1; + value3 >= 0; + value3 = value2) { + int value4 = value2; + Field[] fields2 = fields; + value2--; + classGen.processField2(fields2[value4]); + } + List values; + List values2 = values = Arrays.asList(fields); + RandomUtils.processValues(values2); + int value5; + for (int value6 = value5 = values2.size() - 1; value6 >= 0; value6 = value5) { + int value7 = value5; + List values3 = values; + value5--; + classGen.processField((Field) values3.get(value7)); + } + } else { + Configuration.getObfuscationOptions(); + if (value >= 100) { + int value8; + Field[] fields3; + for (int value9 = value8 = (fields3 = classGen.getFields()).length - 1; + value9 >= 0; + value9 = value8) { + int value10 = value8; + Field[] fields4 = fields3; + value8--; + classGen.processField2(fields4[value10]); + } + List values4 = Arrays.asList(fields3); + Collections.sort(values4, new FieldOrderComparator(this, value)); + int value11; + for (int value12 = value11 = values4.size() - 1; value12 >= 0; value12 = value11) { + int value13 = value11; + value11--; + classGen.processField((Field) values4.get(value13)); + } + } + } + } + + public void processCount2(ClassGen classGen, int value) { + Configuration.getObfuscationOptions(); + if (value == 1) { + Method[] methods; + int value2; + for (int value3 = value2 = (methods = classGen.getMethods()).length - 1; + value3 >= 0; + value3 = value2) { + int value4 = value2; + Method[] methods2 = methods; + value2--; + classGen.processMethod(methods2[value4]); + } + List values = Arrays.asList(methods); + RandomUtils.processValues(values); + int value5; + for (int value6 = value5 = values.size() - 1; value6 >= 0; value6 = value5) { + int value7 = value5; + Method[] methods3 = methods; + value5--; + classGen.processMethod2(methods3[value7]); + } + } else { + Configuration.getObfuscationOptions(); + if (value >= 100) { + Method[] methods4; + int value8; + for (int value9 = value8 = (methods4 = classGen.getMethods()).length - 1; + value9 >= 0; + value9 = value8) { + int value10 = value8; + Method[] methods5 = methods4; + value8--; + classGen.processMethod(methods5[value10]); + } + List values2 = Arrays.asList(methods4); + Collections.sort(values2, new MethodOrderComparator(this, value)); + int value11; + for (int value12 = value11 = values2.size() - 1; value12 >= 0; value12 = value11) { + int value13 = value11; + Method[] methods6 = methods4; + value11--; + classGen.processMethod2(methods6[value13]); + } + } + } + } +} diff --git a/src/main/java/com/allatori/transform/MemberVisibilityTransformer.java b/src/main/java/com/allatori/transform/MemberVisibilityTransformer.java new file mode 100644 index 0000000..fa4966c --- /dev/null +++ b/src/main/java/com/allatori/transform/MemberVisibilityTransformer.java @@ -0,0 +1,202 @@ +package com.allatori.transform; + +import com.allatori.bytecode.MethodFactory; +import com.allatori.config.Configuration; +import com.allatori.lib.bcel.classfile.Attribute; +import com.allatori.lib.bcel.classfile.EnclosingMethod; +import com.allatori.lib.bcel.classfile.ExceptionTable; +import com.allatori.lib.bcel.classfile.Field; +import com.allatori.lib.bcel.classfile.InnerClasses; +import com.allatori.lib.bcel.classfile.Method; +import com.allatori.lib.bcel.classfile.MethodParameters; +import com.allatori.lib.bcel.classfile.RuntimeVisibleParameterAnnotations; +import com.allatori.lib.bcel.classfile.Signature; +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.lib.bcel.generic.FieldGen; +import com.allatori.lib.bcel.generic.MethodGen; +import com.allatori.model.ClassStorage; + +public class MemberVisibilityTransformer implements ClassTransformer { + + public ClassStorage classStorage; + + public void processFieldGen(ClassGen classGen, MethodGen methodGen, FieldGen fieldGen) { + Attribute[] attributes = null; + if (classGen != null && methodGen == null && fieldGen == null) { + attributes = classGen.getAttributes(); + } + if (methodGen != null) { + attributes = methodGen.getAttributes(); + } + if (fieldGen != null) { + attributes = fieldGen.getAttributes(); + } + if (attributes != null) { + int value; + for (int value2 = value = attributes.length - 1; value2 >= 0; value2 = --value) { + if (attributes[value] instanceof Signature) { + if (methodGen != null) { + methodGen.removeAttribute(attributes[value]); + } else if (fieldGen != null) { + fieldGen.removeAttribute(attributes[value]); + } else { + classGen.processAttribute2(attributes[value]); + } + } + } + } + } + + @Override + public void finish() {} + + @Override + public void transform(ClassGen classGen) { + int value; + if (Configuration.getObfuscationOptions().matchesClassGen(this.classStorage, classGen)) { + this.processFieldGen(classGen, null, null); + int value2; + Method[] methods; + for (int value3 = value2 = (methods = classGen.getMethods()).length - 1; + value3 >= 0; + value3 = --value2) { + Attribute[] attributes; + int value4; + Method method; + if ((attributes = (method = methods[value2]).getAttributes()) != null) { + for (int value5 = value4 = attributes.length - 1; value5 >= 0; value5 = --value4) { + if (attributes[value4] instanceof Signature) { + MethodGen methodGen = + MethodFactory.createMethodGen( + method, + classGen.getClassName(), + classGen.getConstantPool(), + classGen.getConstantPool().getConstantPool()); + this.processFieldGen(null, methodGen, null); + classGen.replaceMethod(method, methodGen.getMethod()); + } + } + } + } + int value6; + Field[] fields; + for (int value7 = value6 = (fields = classGen.getFields()).length - 1; + value7 >= 0; + value7 = --value6) { + int value8; + Attribute[] attributes2; + Field field; + if ((attributes2 = (field = fields[value6]).getAttributes()) != null) { + for (int value9 = value8 = attributes2.length - 1; value9 >= 0; value9 = --value8) { + if (attributes2[value8] instanceof Signature) { + FieldGen fieldGen = new FieldGen(field, classGen.getConstantPool()); + this.processFieldGen(null, null, fieldGen); + classGen.replaceField(field, fieldGen.getField()); + } + } + } + } + } + if (Configuration.getObfuscationOptions().matchesClassGen2(this.classStorage, classGen)) { + this.transform2(classGen); + } + int value10; + Method[] methods2; + for (int value11 = value10 = (methods2 = classGen.getMethods()).length - 1; + value11 >= 0; + value11 = --value10) { + Method method2 = methods2[value10]; + int value12; + Attribute[] attributes3; + if (Configuration.getObfuscationOptions().matchesMethod(this.classStorage, classGen, method2) + && (attributes3 = method2.getAttributes()) != null) { + for (int value13 = value12 = attributes3.length - 1; value13 >= 0; value13 = --value12) { + if (attributes3[value12] instanceof ExceptionTable) { + MethodGen methodGen2 = + MethodFactory.createMethodGen( + method2, + classGen.getClassName(), + classGen.getConstantPool(), + classGen.getConstantPool().getConstantPool()); + methodGen2.removeExceptions(); + classGen.replaceMethod(method2, methodGen2.getMethod()); + break; + } + } + } + } + int value14; + Method[] methods3; + for (int value15 = value14 = (methods3 = classGen.getMethods()).length - 1; + value15 >= 0; + value15 = --value14) { + Method method3 = methods3[value14]; + int value16; + value15 = + value16 = + Configuration.getRenamingOptions() + .getLocalVariableOptions() + .calculateCount(this.classStorage, classGen, method3); + Configuration.getRenamingOptions().getLocalVariableOptions(); + if (value15 != 3) { + Configuration.getRenamingOptions().getLocalVariableOptions(); + Attribute[] attributes4; + if (value16 != 5 && (attributes4 = method3.getAttributes()) != null) { + byte value17 = 0; + int value18; + value15 = value18 = attributes4.length - 1; + while (true) { + if (value15 < 0) { + value = value17; + break; + } + if (attributes4[value18] instanceof RuntimeVisibleParameterAnnotations) { + value = 1; + break; + } + value15 = --value18; + } + int value19; + if (value == 0) { + for (int value20 = value19 = attributes4.length - 1; + value20 >= 0; + value20 = --value19) { + if (attributes4[value19] instanceof MethodParameters) { + MethodGen methodGen3 = + MethodFactory.createMethodGen( + method3, + classGen.getClassName(), + classGen.getConstantPool(), + classGen.getConstantPool().getConstantPool()); + methodGen3.removeAttribute(attributes4[value19]); + classGen.replaceMethod(method3, methodGen3.getMethod()); + break; + } + } + } + } + } + } + } + + public MemberVisibilityTransformer(ClassStorage classStorage2) { + super(); + this.classStorage = classStorage2; + } + + public void transform2(ClassGen classGen) { + Attribute[] attributes = null; + if (classGen != null) { + attributes = classGen.getAttributes(); + } + if (attributes != null) { + int value; + for (int value2 = value = attributes.length - 1; value2 >= 0; value2 = --value) { + if (attributes[value] instanceof InnerClasses + || attributes[value] instanceof EnclosingMethod) { + classGen.processAttribute2(attributes[value]); + } + } + } + } +} diff --git a/src/main/java/com/allatori/transform/MethodAccessTransformer.java b/src/main/java/com/allatori/transform/MethodAccessTransformer.java new file mode 100644 index 0000000..1595213 --- /dev/null +++ b/src/main/java/com/allatori/transform/MethodAccessTransformer.java @@ -0,0 +1,46 @@ +package com.allatori.transform; + +import com.allatori.config.Configuration; +import com.allatori.lib.bcel.classfile.Field; +import com.allatori.lib.bcel.classfile.Method; +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.model.ClassStorage; + +public class MethodAccessTransformer implements ClassTransformer { + + public ClassStorage classStorage; + + @Override + public void transform(ClassGen classGen) { + try { + int value; + Field[] fields; + for (int value2 = value = (fields = classGen.getFields()).length - 1; + value2 >= 0; + value2 = --value) { + Field field = fields[value]; + if (Configuration.getSyntheticOptions().matchesField(this.classStorage, classGen, field)) { + field.processEnabled9(true); + } + } + Method[] methods; + for (int value3 = (methods = classGen.getMethods()).length - 1; value3 >= 0; value3--) { + Method method = methods[value3]; + if (Configuration.getSyntheticOptions() + .matchesMethod(this.classStorage, classGen, method)) { + method.processEnabled9(true); + } + } + } catch (Exception exception) { + exception.printStackTrace(); + } + } + + public MethodAccessTransformer(ClassStorage classStorage2) { + super(); + this.classStorage = classStorage2; + } + + @Override + public void finish() {} +} diff --git a/src/main/java/com/allatori/transform/MethodOrderComparator.java b/src/main/java/com/allatori/transform/MethodOrderComparator.java new file mode 100644 index 0000000..dc0bef3 --- /dev/null +++ b/src/main/java/com/allatori/transform/MethodOrderComparator.java @@ -0,0 +1,31 @@ +package com.allatori.transform; + +import com.allatori.config.Configuration; +import com.allatori.lib.bcel.classfile.Method; +import java.util.Comparator; + +public class MethodOrderComparator implements Comparator { + + public final int count; + + public final MemberReorderTransformer memberReorderTransformer; + + @Override + public int compare(Object result, Object result2) { + return this.calculateCount((Method) result, (Method) result2); + } + + public MethodOrderComparator(MemberReorderTransformer memberReorderTransformer2, int count) { + super(); + this.memberReorderTransformer = memberReorderTransformer2; + this.count = count; + } + + public int calculateCount(Method method, Method method2) { + int value = this.count; + Configuration.getObfuscationOptions(); + return value == 100 + ? method2.getText().compareTo(method.getText()) + : method.getText().compareTo(method2.getText()); + } +} diff --git a/src/main/java/com/allatori/transform/OptimizerTransformer.java b/src/main/java/com/allatori/transform/OptimizerTransformer.java new file mode 100644 index 0000000..8f7c440 --- /dev/null +++ b/src/main/java/com/allatori/transform/OptimizerTransformer.java @@ -0,0 +1,27 @@ +package com.allatori.transform; + +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.model.ClassStorage; +import com.allatori.optimizer.MethodOptimizer; + +public class OptimizerTransformer implements ClassTransformer { + + public ClassStorage classStorage; + + @Override + public void finish() { + this.finish2(); + } + + public void finish2() {} + + public OptimizerTransformer(ClassStorage classStorage2) { + super(); + this.classStorage = classStorage2; + } + + @Override + public void transform(ClassGen classGen) { + new MethodOptimizer(this.classStorage).notify(classGen); + } +} diff --git a/src/main/java/com/allatori/transform/RemoveFieldsTransformer.java b/src/main/java/com/allatori/transform/RemoveFieldsTransformer.java new file mode 100644 index 0000000..232bb7e --- /dev/null +++ b/src/main/java/com/allatori/transform/RemoveFieldsTransformer.java @@ -0,0 +1,43 @@ +package com.allatori.transform; + +import com.allatori.config.Configuration; +import com.allatori.lib.bcel.classfile.Field; +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.model.ClassStorage; +import com.allatori.util.Log; + +public class RemoveFieldsTransformer implements ClassTransformer { + + public ClassStorage classStorage; + + @Override + public void transform(ClassGen classGen) { + int value; + Field[] fields; + for (int value2 = value = (fields = classGen.getFields()).length - 1; + value2 >= 0; + value2 = --value) { + Field field = fields[value]; + if (Configuration.getFieldRemovalOptions().matchesField(this.classStorage, classGen, field)) { + classGen.processField2(field); + String text = "" + classGen.getClassName() + "." + field.getText() + field.getText2(); + Configuration.getFieldRemovalOptions().processText(text); + Log.info( + " [remove-fields] removed " + + classGen.getClassName() + + "." + + field.getText() + + " " + + field.getText2()); + } + } + } + + @Override + public void finish() {} + + public RemoveFieldsTransformer(ClassStorage classStorage2) { + super(); + this.classStorage = classStorage2; + } +} diff --git a/src/main/java/com/allatori/transform/RemoveMethodsTransformer.java b/src/main/java/com/allatori/transform/RemoveMethodsTransformer.java new file mode 100644 index 0000000..083443e --- /dev/null +++ b/src/main/java/com/allatori/transform/RemoveMethodsTransformer.java @@ -0,0 +1,46 @@ +package com.allatori.transform; + +import com.allatori.config.Configuration; +import com.allatori.lib.bcel.classfile.Method; +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.model.ClassStorage; +import com.allatori.util.Log; + +public class RemoveMethodsTransformer implements ClassTransformer { + + public ClassStorage classStorage; + + @Override + public void transform(ClassGen classGen) { + String text = "toString"; + String text2 = "()Ljava/lang/String;"; + int value; + Method[] methods; + for (int value2 = value = (methods = classGen.getMethods()).length - 1; + value2 >= 0; + value2 = --value) { + Method method = methods[value]; + if (Configuration.getOptimizationOptions().matchesClassGen(this.classStorage, classGen) + && text.equals(method.getText()) + && text2.equals(method.getText2())) { + classGen.processMethod(method); + Log.info(" [remove-methods] removed " + classGen.getClassName() + "." + text + text2); + } + if (Configuration.getOptimizationOptions() + .matchesMethod(this.classStorage, classGen, method)) { + classGen.processMethod(method); + String text3 = "" + classGen.getClassName() + "." + method.getText() + method.getText2(); + Configuration.getOptimizationOptions().processText(text3); + Log.info(" [remove-methods] removed " + text3); + } + } + } + + @Override + public void finish() {} + + public RemoveMethodsTransformer(ClassStorage classStorage2) { + super(); + this.classStorage = classStorage2; + } +} diff --git a/src/main/java/com/allatori/transform/StripAttributesTransformer.java b/src/main/java/com/allatori/transform/StripAttributesTransformer.java new file mode 100644 index 0000000..1209245 --- /dev/null +++ b/src/main/java/com/allatori/transform/StripAttributesTransformer.java @@ -0,0 +1,50 @@ +package com.allatori.transform; + +import com.allatori.config.Configuration; +import com.allatori.lib.bcel.classfile.InnerClass; +import com.allatori.lib.bcel.classfile.InnerClasses; +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.model.ClassStorage; +import java.util.Iterator; +import java.util.Vector; + +public class StripAttributesTransformer implements ClassTransformer { + + public ClassStorage classStorage; + + public StripAttributesTransformer(ClassStorage classStorage2) { + super(); + this.classStorage = classStorage2; + } + + @Override + public void finish() {} + + @Override + public void transform(ClassGen classGen) { + String text; + if ((text = Configuration.getMethodRemovalOptions().getTestString()) != null) { + ClassGen classGen2; + if ((classGen2 = this.classStorage.getClassGen(text)) != null) { + Vector vector = new Vector(); + Iterator classesByName2 = this.classStorage.getClassesByName2(); + String text2 = "" + text + "$"; + while (classesByName2.hasNext()) { + ClassGen classGen3; + if ((classGen3 = (ClassGen) classesByName2.next()).getClassName().startsWith(text2)) { + InnerClass innerClass = + new InnerClass( + classGen2.getConstantPool().addClass(classGen3.getClassName()), 0, 0, 0); + vector.add(innerClass); + } + } + classGen2.processAttribute( + new InnerClasses( + classGen2.getConstantPool().addUtf8("InnerClasses"), + vector.size() * 8 + 2, + (InnerClass[]) vector.toArray(new InnerClass[0]), + classGen2.getConstantPool().getConstantPool())); + } + } + } +} diff --git a/src/main/java/com/allatori/util/FileUtils.java b/src/main/java/com/allatori/util/FileUtils.java new file mode 100644 index 0000000..84d1774 --- /dev/null +++ b/src/main/java/com/allatori/util/FileUtils.java @@ -0,0 +1,100 @@ +package com.allatori.util; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.UnsupportedEncodingException; +import java.nio.MappedByteBuffer; +import java.nio.channels.FileChannel; +import java.nio.channels.FileChannel.MapMode; +import java.util.Vector; + +public class FileUtils { + + public static String createText(File file, String text) + throws FileNotFoundException, UnsupportedEncodingException, IOException { + StringBuffer stringBuffer = new StringBuffer((int) file.length()); + BufferedReader bufferedReader; + BufferedReader bufferedReader2 = + text != null + ? (bufferedReader = + new BufferedReader(new InputStreamReader(new FileInputStream(file), text))) + : (bufferedReader = new BufferedReader(new FileReader(file))); + int value; + while ((value = bufferedReader2.read()) != -1) { + bufferedReader2 = bufferedReader; + stringBuffer.append((char) value); + } + bufferedReader.close(); + return stringBuffer.toString(); + } + + public static void processFile(File file, File file2) throws IOException, FileNotFoundException { + FileChannel fileChannel = null; + FileChannel fileChannel2 = null; + try { + fileChannel = new FileInputStream(file).getChannel(); + fileChannel2 = new FileOutputStream(file2).getChannel(); + MappedByteBuffer mappedByteBuffer = + fileChannel.map(MapMode.READ_ONLY, 0L, fileChannel.size()); + fileChannel2.write(mappedByteBuffer); + } finally { + if (fileChannel != null) { + fileChannel.close(); + } + if (fileChannel2 != null) { + fileChannel2.close(); + } + } + } + + public static String[] createTexts(File file, String text, boolean matches) + throws FileNotFoundException, UnsupportedEncodingException, IOException { + BufferedReader bufferedReader; + if (text != null) { + bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(file), text)); + } else { + bufferedReader = new BufferedReader(new FileReader(file)); + } + Vector vector = new Vector(); + label25: + while (true) { + BufferedReader bufferedReader2 = bufferedReader; + String text2; + while ((text2 = bufferedReader2.readLine()) != null) { + if (matches) { + if (text2.length() <= 0) { + continue label25; + } + bufferedReader2 = bufferedReader; + vector.add(text2); + } else { + vector.add(text2); + bufferedReader2 = bufferedReader; + } + } + bufferedReader.close(); + String[] texts = new String[vector.size()]; + return (String[]) vector.toArray(texts); + } + } + + public static void processText(File file, String text, String text2) + throws FileNotFoundException, UnsupportedEncodingException, IOException { + BufferedWriter bufferedWriter; + (text != null + ? (bufferedWriter = + new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), text))) + : (bufferedWriter = new BufferedWriter(new FileWriter(file)))) + .write(text2); + bufferedWriter.close(); + } +} diff --git a/src/main/java/com/allatori/util/Log.java b/src/main/java/com/allatori/util/Log.java new file mode 100644 index 0000000..f19e689 --- /dev/null +++ b/src/main/java/com/allatori/util/Log.java @@ -0,0 +1,47 @@ +package com.allatori.util; + +import com.allatori.naming.MappingXmlWriter; + +public class Log { + + public static boolean silent = false; + + public static void error(String text) { + MappingXmlWriter.stringBuilder.append("[ERROR] " + text + "\n"); + System.out.println("[ERROR] " + text); + } + + public static void info(String text) { + if (!silent) { + MappingXmlWriter.stringBuilder.append("[INFO] " + text + "\n"); + System.out.println("[INFO] " + text); + } + } + + public static boolean isSilent() { + return silent; + } + + public static void warn(String text) { + if (!silent) { + MappingXmlWriter.stringBuilder.append("[WARNING] " + text + "\n"); + System.out.println("[WARNING] " + text); + } + } + + public static void info2(String text) { + if (!silent) { + System.out.println("[INFO] " + text); + } + } + + public static void setSilent(boolean matches) { + silent = matches; + } + + public static void debug(String text) { + if (!silent) { + System.out.println("[DEBUG] " + text); + } + } +} diff --git a/src/main/java/com/allatori/util/LookupTable.java b/src/main/java/com/allatori/util/LookupTable.java new file mode 100644 index 0000000..c21dac7 --- /dev/null +++ b/src/main/java/com/allatori/util/LookupTable.java @@ -0,0 +1,33 @@ +package com.allatori.util; + +import java.util.Hashtable; +import java.util.Set; + +public class LookupTable { + + public Hashtable entries = new Hashtable(); + + public int getEntries() { + return this.entries.size(); + } + + public Set getEntries2() { + return this.entries.keySet(); + } + + public void processText(String text, String text2) { + this.entries.put(text, text2); + } + + public boolean matchesText(String text) { + return this.entries.containsKey(text); + } + + public void processText(String text) { + this.entries.remove(text); + } + + public String getText(String text) { + return (String) this.entries.get(text); + } +} diff --git a/src/main/java/com/allatori/util/StreamUtils.java b/src/main/java/com/allatori/util/StreamUtils.java new file mode 100644 index 0000000..3e02ad7 --- /dev/null +++ b/src/main/java/com/allatori/util/StreamUtils.java @@ -0,0 +1,141 @@ +package com.allatori.util; + +import com.allatori.config.Configuration; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Reader; +import java.io.UnsupportedEncodingException; +import java.io.Writer; + +public class StreamUtils { + + public static void processWriter(Reader reader, Writer writer) throws IOException { + StringBuffer stringBuffer = new StringBuffer(); + int value; + while ((value = reader.read()) >= 0) { + char value2 = (char) value; + if (stringBuffer.length() == 0) { + if (Character.isJavaIdentifierStart(value2)) { + stringBuffer.append(value2); + } else { + writer.write(value2); + } + } else if (!Character.isJavaIdentifierPart(value2) && value2 != '.' && value2 != '-') { + processText(writer, stringBuffer.toString()); + stringBuffer.setLength(0); + writer.write(value2); + } else { + stringBuffer.append(value2); + } + } + processText(writer, stringBuffer.toString()); + } + + public static void processText(InputStream inputStream, OutputStream outputStream, String text) + throws UnsupportedEncodingException, IOException { + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, text)); + BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream, text)); + processWriter(bufferedReader, bufferedWriter); + bufferedWriter.flush(); + outputStream.flush(); + } + + public static void processText(Writer writer, String text) throws IOException { + String text2; + if ((text2 = Configuration.getMappingOptions().renamingLog.lookupTable4.getText(text)) + != null) { + writer.write(text2); + } else { + writer.write(text); + } + } + + public static String createText(String text, String text2) { + String text3 = text; + if (text3 == null) { + text3 = ""; + } + String text4; + if (text3.length() > 0) { + if (!text2.startsWith(text3)) { + return text2; + } + text4 = text2 = text2.substring(text3.length()); + } else { + text4 = text2; + } + String[] texts; + String[] texts2 = texts = text4.split("/"); + String text5 = texts2[texts2.length - 1]; + String text6 = ""; + if (text5.contains(".")) { + text6 = text5.substring(text5.indexOf(46)); + text5 = text5.substring(0, text5.indexOf(46)); + } + String text7 = ""; + int value; + for (int value2 = value = 0; value2 < texts.length - 1; value2 = value) { + StringBuilder stringBuilder = new StringBuilder().insert(0, text7).append(texts[value]); + value++; + text7 = stringBuilder.append((char) '.').toString(); + } + String text8 = "" + text7 + text5; + if (Configuration.getMappingOptions().renamingLog.lookupTable4.matchesText(text8)) { + return "" + + text3 + + Configuration.getMappingOptions() + .renamingLog + .lookupTable4 + .getText(text8) + .replace('.', '/') + + text6; + } + while (text5.contains("_")) { + text6 = "" + text5.substring(text5.lastIndexOf(95)) + text6; + text5 = text5.substring(0, text5.lastIndexOf(95)); + String text9 = "" + text7 + text5; + if (Configuration.getMappingOptions().renamingLog.lookupTable4.matchesText(text9)) { + return "" + + text3 + + Configuration.getMappingOptions() + .renamingLog + .lookupTable4 + .getText(text9) + .replace('.', '/') + + text6; + } + } + int value3; + for (int value4 = value3 = texts.length - 2; value4 >= 0; value4 = --value3) { + String text10 = ""; + int value5; + for (int value6 = value5 = 0; value6 < value3; value6 = value5) { + StringBuilder stringBuilder2 = new StringBuilder().insert(0, text10).append(texts[value5]); + value5++; + text10 = stringBuilder2.append((char) '.').toString(); + } + String text11 = "" + text10 + texts[value3]; + if (Configuration.getMappingOptions().lookupTable2.matchesText(text11) + && !text11.equals(Configuration.getMappingOptions().lookupTable2.getText(text11))) { + String text12 = + "" + + text3 + + Configuration.getMappingOptions().lookupTable2.getText(text11).replace('.', '/'); + int value7; + for (int value8 = value7 = value3 + 1; value8 <= texts.length - 1; value8 = value7) { + StringBuilder stringBuilder3 = new StringBuilder().insert(0, text12).append('/'); + String text13 = texts[value7]; + value7++; + text12 = stringBuilder3.append(text13).toString(); + } + return text12; + } + } + return "" + text3 + text2; + } +} diff --git a/src/main/java/com/allatori/util/random/RandomGenerator.java b/src/main/java/com/allatori/util/random/RandomGenerator.java new file mode 100644 index 0000000..7dc2107 --- /dev/null +++ b/src/main/java/com/allatori/util/random/RandomGenerator.java @@ -0,0 +1,77 @@ +package com.allatori.util.random; + +public abstract class RandomGenerator implements Cloneable { + + public Double cachedGaussian; + + public int nextInt(int value) { + return this.nextInt(1, value); + } + + public double nextGaussian() { + if (this.cachedGaussian != null) { + double value = this.cachedGaussian; + this.cachedGaussian = null; + return value; + } + double value2; + double value3; + double value4; + do { + value2 = this.nextDouble(-1.0, 1.0); + value4 = this.nextDouble(-1.0, 1.0); + } while ((value3 = value2 * value2 + value4 * value4) >= 1.0); + double value5 = Math.sqrt(-2.0 * Math.log(value3) / value3); + this.cachedGaussian = new Double(value2 * value5); + return value4 * value5; + } + + public boolean nextBoolean() { + return this.nextDouble() <= 0.5; + } + + public double nextDouble(double value, double value2) { + return value + (value2 - value) * this.nextDouble(); + } + + public double nextGaussian(double value) { + return this.nextGaussian() * value; + } + + public double nextPowerLaw(double value, double value2) { + return value2 * Math.pow(this.nextDouble(), 1.0 / (value + 1.0)); + } + + public void fill(double[] values) { + this.fill(values, values.length); + } + + public int nextInt(int value, int value2) { + int value3; + if ((value3 = value + (int) ((value2 - value) * this.nextDouble())) > value2) { + value3 = value2; + } + return value3; + } + + public void fill(double[] values, int value) { + int value2; + for (int value3 = value2 = 0; value3 < value; value3 = value2) { + double value4 = this.nextDouble(); + int value5 = value2; + value2++; + values[value5] = value4; + } + } + + public boolean nextBoolean(double value) { + return this.nextDouble() <= value; + } + + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } + + public abstract double nextDouble(); +} diff --git a/src/main/java/com/allatori/util/random/RandomUtils.java b/src/main/java/com/allatori/util/random/RandomUtils.java new file mode 100644 index 0000000..407cc6b --- /dev/null +++ b/src/main/java/com/allatori/util/random/RandomUtils.java @@ -0,0 +1,82 @@ +package com.allatori.util.random; + +import com.allatori.config.Configuration; +import java.util.List; +import java.util.ListIterator; +import java.util.RandomAccess; + +public class RandomUtils { + + public static boolean enabled = false; + + public static RandomGenerator randomGenerator; + + public static void processCount(List values, int value, int value2) { + values.set(value, values.set(value2, values.get(value))); + } + + public static double calculateValue() { + if (!enabled) { + update(); + } + return randomGenerator.nextDouble(); + } + + public static void processCount(Object[] results, int value, int value2) { + Object result = results[value]; + results[value] = results[value2]; + results[value2] = result; + } + + public static int calculateCount(int value) { + if (!enabled) { + update(); + } + int value2; + return (value2 = randomGenerator.nextInt(0, value)) < value ? value2 : value2 - 1; + } + + public static void update() { + String text; + if ((text = Configuration.getObfuscationOptions().getRandomSeed()) != null + && text.length() != 0) { + randomGenerator = new RanmarRandom(text.hashCode()); + } else { + randomGenerator = new RanmarRandom(System.currentTimeMillis()); + } + enabled = true; + } + + public static void processValues(List values) { + if (!enabled) { + update(); + } + int value; + int value2; + if ((value = values.size()) >= 5 && !(values instanceof RandomAccess)) { + Object[] results = values.toArray(); + int value3; + for (int value4 = value3 = value; value4 > 1; value4 = value3) { + int value5 = value3 - 1; + int value6 = value3; + value3--; + processCount(results, value5, calculateCount(value6)); + } + ListIterator listIterator2 = values.listIterator(); + int value7; + for (int value8 = value7 = 0; value8 < results.length; value8 = value7) { + listIterator2.next(); + int value9 = value7; + value7++; + listIterator2.set(results[value9]); + } + } else { + for (int value10 = value2 = value; value10 > 1; value10 = value2) { + int value11 = value2 - 1; + int value12 = value2; + value2--; + processCount(values, value11, calculateCount(value12)); + } + } + } +} diff --git a/src/main/java/com/allatori/util/random/RanmarRandom.java b/src/main/java/com/allatori/util/random/RanmarRandom.java new file mode 100644 index 0000000..f0403a8 --- /dev/null +++ b/src/main/java/com/allatori/util/random/RanmarRandom.java @@ -0,0 +1,136 @@ +package com.allatori.util.random; + +import java.io.Serializable; +import java.util.Date; + +public class RanmarRandom extends SeededRandomGenerator implements Serializable { + + public double carry; + + public double[] savedState; + + public int j97; + + public double[] state; + + public double carryDelta; + + public int i97; + + public static int DEFAULT_SEED = 54217137; + + public static int SEED_MODULUS = 899999963; + + public double carryModulus; + + public RanmarRandom() { + this.initializeState(DEFAULT_SEED); + } + + public void initializeState(int value) { + this.state = new double[97]; + this.savedState = new double[97]; + int value2 = value / 30082; + int value3 = value - 30082 * value2; + int value4 = value2 / 177 % 177 + 2; + int value5 = value2 % 177 + 2; + int value6 = value3 / 169 % 178 + 1; + int value7 = value3 % 169; + int value8; + for (int value9 = value8 = 0; value9 < 97; value9 = value8) { + double value10 = 0.0; + double value11 = 0.5; + int value12; + for (int value13 = value12 = 0; value13 < 24; value13 = value12) { + int value14 = value4 * value5 % 179 * value6 % 179; + value4 = value5; + value5 = value6; + value6 = value14; + if ((value7 = (53 * value7 + 1) % 169) * value14 % 64 >= 32) { + value10 += value11; + } + double value15 = value11; + value12++; + value11 = value15 * 0.5; + } + double value16 = value10; + int value17 = value8; + double[] values = this.state; + value8++; + values[value17] = value16; + } + this.carry = 0.021602869F; + this.carryDelta = 0.45623308F; + this.carryModulus = 0.9999998F; + this.i97 = 96; + this.j97 = 32; + } + + @Override + public final double nextDouble() { + double value; + if ((value = this.state[this.i97] - this.state[this.j97]) < 0.0) { + value++; + } + this.state[this.i97] = value; + if (--this.i97 < 0) { + this.i97 = 96; + } + if (--this.j97 < 0) { + this.j97 = 96; + } + this.carry = this.carry - this.carryDelta; + if (this.carry < 0.0) { + this.carry = this.carry + this.carryModulus; + } + double value2; + if ((value2 = value - this.carry) < 0.0) { + value2++; + } + return value2; + } + + public RanmarRandom(int value) { + super(); + this.initializeState(Math.abs(value % SEED_MODULUS)); + } + + @Override + public final void fill(double[] values, int value) { + int value2; + for (int value3 = value2 = 0; value3 < value; value3 = value2) { + double value4; + if ((value4 = this.state[this.i97] - this.state[this.j97]) < 0.0) { + value4++; + } + this.state[this.i97] = value4; + if (--this.i97 < 0) { + this.i97 = 96; + } + if (--this.j97 < 0) { + this.j97 = 96; + } + this.carry = this.carry - this.carryDelta; + if (this.carry < 0.0) { + this.carry = this.carry + this.carryModulus; + } + double value5; + if ((value5 = value4 - this.carry) < 0.0) { + value5++; + } + double value6 = value5; + int value7 = value2; + value2++; + values[value7] = value6; + } + } + + public RanmarRandom(long value) { + this.initializeState((int) Math.abs(value % SEED_MODULUS)); + } + + public RanmarRandom(Date date) { + super(); + this.initializeState((int) calculateSeed(date) % SEED_MODULUS); + } +} diff --git a/src/main/java/com/allatori/util/random/SeededRandomGenerator.java b/src/main/java/com/allatori/util/random/SeededRandomGenerator.java new file mode 100644 index 0000000..fc7bb0c --- /dev/null +++ b/src/main/java/com/allatori/util/random/SeededRandomGenerator.java @@ -0,0 +1,14 @@ +package com.allatori.util.random; + +import java.util.Date; + +public abstract class SeededRandomGenerator extends RandomGenerator { + + public static long calculateSeed(Date date) { + return date.getTime(); + } + + public static long calculateSeed() { + return calculateSeed(new Date()); + } +} diff --git a/src/main/java/com/allatori/watermark/WatermarkProcessor.java b/src/main/java/com/allatori/watermark/WatermarkProcessor.java new file mode 100644 index 0000000..9468bee --- /dev/null +++ b/src/main/java/com/allatori/watermark/WatermarkProcessor.java @@ -0,0 +1,543 @@ +package com.allatori.watermark; + +import com.allatori.VersionInfo; +import com.allatori.config.Configuration; +import com.allatori.engine.ObfuscationException; +import com.allatori.lib.bcel.classfile.Method; +import com.allatori.lib.bcel.generic.ClassGen; +import com.allatori.lib.bcel.generic.ICONST; +import com.allatori.lib.bcel.generic.InstructionConstants; +import com.allatori.lib.bcel.generic.InstructionHandle; +import com.allatori.lib.bcel.generic.InstructionList; +import com.allatori.lib.bcel.generic.InstructionTargeter; +import com.allatori.lib.bcel.generic.LineNumberGen; +import com.allatori.lib.bcel.generic.LocalVariableGen; +import com.allatori.lib.bcel.generic.POP2; +import com.allatori.lib.bcel.generic.SIPUSH; +import com.allatori.lib.bcel.util.comparator.MethodComparator; +import com.allatori.model.ClassStorage; +import com.allatori.model.MethodContext; +import com.allatori.util.Log; +import com.allatori.util.random.RandomUtils; +import java.io.UnsupportedEncodingException; +import java.util.Arrays; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.Vector; + +public class WatermarkProcessor { + + public ClassStorage classStorage; + + public String watermarkKey; + + public void processValues(Vector vector, short[] values) { + InstructionHandle instructionHandle; + int value = values.length / 4; + int size2 = vector.size(); + int value2 = (value - 1) / size2 + 1; + int value3 = 0; + int value4; + for (int value5 = value4 = vector.size() - 1; value5 >= 0; value5 = value4) { + InstructionHandle instructionHandle2; + MethodContext methodContext; + InstructionList instructionList; + InstructionHandle instructionHandle3 = + instructionHandle2 = + (instructionList = + MethodContext.getMethodGen(methodContext = (MethodContext) vector.get(value4)) + .getInstructionList()) + .getStart(); + while (true) { + if (instructionHandle3 == null) { + instructionHandle = instructionHandle2; + break; + } + if (instructionHandle2.getInstruction() instanceof ICONST + && this.matchesInstructionTargeters(instructionHandle2.getTargeters()) + && instructionHandle2.getInstructionHandle2() != null) { + instructionHandle = instructionHandle2 = instructionHandle2.getInstructionHandle2(); + break; + } + instructionHandle3 = instructionHandle2 = instructionHandle2.getInstructionHandle2(); + } + if (instructionHandle == null) { + instructionHandle2 = instructionList.getStart(); + } + if (Configuration.getObfuscationOptions().isEnabled()) { + instructionHandle2 = instructionList.getEnd(); + } + int value6 = 0; + do { + InstructionHandle instructionHandle4 = + instructionList.createInstructionHandle(instructionHandle2, new SIPUSH(values[value3])); + InstructionHandle instructionHandle5 = + instructionList.createInstructionHandle( + instructionHandle2, new SIPUSH(values[++value3])); + InstructionHandle instructionHandle6 = + instructionList.createInstructionHandle( + instructionHandle2, new SIPUSH(values[++value3])); + InstructionHandle instructionHandle7 = + instructionList.createInstructionHandle( + instructionHandle2, new SIPUSH(values[++value3])); + value3++; + InstructionHandle instructionHandle8; + InstructionHandle instructionHandle9 = + instructionHandle8 = + instructionList.createInstructionHandle( + instructionHandle2, InstructionConstants.POP2); + instructionList.createInstructionHandle(instructionHandle2, InstructionConstants.POP2); + value6++; + instructionHandle2 = instructionList.getStart(); + } while (value6 < value2 && value4 < value - value3 / 4); + MethodContext.getMethodGen(methodContext).update5(); + ClassGen classGen = MethodContext.getClassGen(methodContext); + Method method = MethodContext.getMethod(methodContext); + MethodContext methodContext2 = methodContext; + value4--; + classGen.replaceMethod(method, MethodContext.getMethodGen(methodContext2).getMethod()); + } + } + + public short[] createValues(Vector vector) { + Vector vector2 = new Vector(); + int value; + InstructionHandle instructionHandle; + for (int value2 = value = vector.size() - 1; value2 >= 0; value2 = --value) { + for (InstructionHandle instructionHandle2 = + instructionHandle = + MethodContext.getMethodGen((MethodContext) vector.get(value)) + .getInstructionList() + .getStart(); + instructionHandle2 != null; + instructionHandle2 = instructionHandle = instructionHandle.getInstructionHandle2()) { + if (this.matchesInstructionHandle(instructionHandle)) { + vector2.add(((SIPUSH) instructionHandle.getInstruction()).getValue()); + vector2.add( + ((SIPUSH) instructionHandle.getInstructionHandle2().getInstruction()).getValue()); + vector2.add( + ((SIPUSH) + instructionHandle + .getInstructionHandle2() + .getInstructionHandle2() + .getInstruction()) + .getValue()); + vector2.add( + ((SIPUSH) + instructionHandle + .getInstructionHandle2() + .getInstructionHandle2() + .getInstructionHandle2() + .getInstruction()) + .getValue()); + } + } + } + short[] values; + int value3; + for (int value4 = value3 = (values = new short[vector2.size()]).length - 1; + value4 >= 0; + value4 = value3) { + short value5 = ((Number) vector2.get(value3)).shortValue(); + int value6 = value3; + short[] values2 = values; + value3--; + values2[value6] = value5; + } + return values; + } + + public boolean matchesValues(Vector vector) { + InstructionHandle instructionHandle; + int value; + for (int value2 = value = vector.size() - 1; value2 >= 0; value2 = --value) { + for (InstructionHandle instructionHandle2 = + instructionHandle = + MethodContext.getMethodGen((MethodContext) vector.get(value)) + .getInstructionList() + .getStart(); + instructionHandle2 != null; + instructionHandle2 = instructionHandle = instructionHandle.getInstructionHandle2()) { + if (this.matchesInstructionHandle(instructionHandle)) { + return true; + } + } + } + return false; + } + + public String createText(short[] values) throws Exception, UnsupportedEncodingException { + int value; + for (int value2 = value = 0; value2 < values.length; value2 = value) { + short value3 = values[value]; + short value4 = values[value + 1]; + short value5 = values[value + 2]; + short value6 = values[value + 3]; + values[value] = values[value + 1] = values[value + 2] = values[value + 3] = 0; + values[value] = (short) (values[value] | value3 ^ value5 ^ value6); + short[] values2; + if (values[value] % 2 == 0) { + values2 = values; + values[value + 1] = (short) (values[value + 1] | value3 ^ value4 ^ value6); + } else { + values2 = values; + values[value + 1] = (short) (values[value + 1] | value4 ^ value5 ^ values[value]); + } + short[] values3; + if (values2[value + 1] % 4 == 0) { + values3 = values; + values[value + 2] = (short) (values[value + 2] | value3 ^ value4 ^ value5); + } else if (values[value + 1] % 4 == 1) { + values3 = values; + values[value + 2] = + (short) (values[value + 2] | value3 ^ values[value] ^ values[value + 1]); + } else if (values[value + 1] % 4 == 2) { + values3 = values; + values[value + 2] = (short) (values[value + 2] | value5 ^ value6 ^ values[value + 1]); + } else { + values3 = values; + values[value + 2] = (short) (values[value + 2] | value4 ^ value6 ^ values[value]); + } + if (values3[value + 2] % 7 == 0) { + values[value + 3] = (short) (values[value + 3] | value4 ^ value5 ^ value6); + } else if (values[value + 2] % 7 == 1) { + values[value + 3] = + (short) (values[value + 3] | value6 ^ values[value] ^ values[value + 1]); + } else if (values[value + 2] % 7 == 2) { + values[value + 3] = + (short) (values[value + 3] | value5 ^ values[value] ^ values[value + 2]); + } else if (values[value + 2] % 7 == 3) { + values[value + 3] = + (short) (values[value + 3] | value4 ^ values[value + 1] ^ values[value + 2]); + } else if (values[value + 2] % 7 == 4) { + values[value + 3] = (short) (values[value + 3] | value3 ^ value4 ^ values[value]); + } else if (values[value + 2] % 7 == 5) { + values[value + 3] = (short) (values[value + 3] | value3 ^ value5 ^ values[value + 1]); + } else { + values[value + 3] = (short) (values[value + 3] | value3 ^ value6 ^ values[value + 2]); + } + value += 4; + } + int value7 = this.watermarkKey.hashCode(); + short value8 = (short) ((byte) 0 | value7); + short value9 = (short) ((byte) 0 | value7 >> 16); + int value10 = -1; + Hashtable hashtable = new Hashtable(); + int value11; + for (int value12 = value11 = 0; value12 < values.length; value12 = value11) { + hashtable.put(new Short(values[value11]), new Integer(value11)); + if (values[value11] == value8 && values[value11 + 1] == value9) { + if (value10 != -1) { + throw new Exception(); + } + value10 = value11; + } + value11 += 4; + } + if (value10 == -1) { + throw new Exception(); + } + int value13; + int value14 = value13 = values[value10 + 3]; + while (value14 % 4 != 0) { + value14 = ++value13; + } + byte[] values4; + Arrays.fill(values4 = new byte[value13], (byte) 0); + int value15 = 0; + int value16 = value10 + 1; + for (int value17 = value15; value17 < values4.length; value17 = value15) { + value16 = ((Number) hashtable.get(new Short(values[value16 + 1]))).shortValue(); + int value18 = value15; + byte[] values5 = values4; + int value19 = value15; + byte[] values6 = values4; + byte[] values7 = values4; + byte[] values8 = values4; + byte[] values9 = values4; + value15++; + values6[value19] = (byte) (values5[value18] | values[value16 + 2] >> 8); + int value20 = value15; + int value21 = value15; + value15++; + values7[value21] = (byte) (values7[value20] | values[value16 + 3] >> 8); + int value22 = value15; + int value23 = value15; + value15++; + values8[value23] = (byte) (values8[value22] | values[value16 + 2]); + int value24 = value15; + int value25 = value15; + value15++; + values9[value25] = (byte) (values9[value24] | values[value16 + 3]); + } + byte[] bytes = this.watermarkKey.getBytes(); + int value26; + for (int value27 = value26 = 0; value27 < values4.length; value27 = value26) { + byte value28 = (byte) (values4[value26] ^ bytes[value26 % bytes.length]); + int value29 = value26; + byte[] values10 = values4; + value26++; + values10[value29] = value28; + } + if (values4.length > 1) { + values4[1] ^= values4[0]; + } + int value30; + for (int value31 = value30 = 2; value31 < values4.length; value31 = value30) { + byte value32 = (byte) (values4[value30] ^ values4[value30 - 1] ^ values4[value30 - 2]); + int value33 = value30; + byte[] values11 = values4; + value30++; + values11[value33] = value32; + } + return new String(values4, 0, values[value10 + 3], "UTF-8"); + } + + public Vector createValues() { + Vector vector = new Vector(); + Iterator classesByName2 = this.classStorage.getClassesByName2(); + while (true) { + Iterator iterator = classesByName2; + ClassGen classGen; + while (true) { + if (!iterator.hasNext()) { + return vector; + } + classGen = (ClassGen) classesByName2.next(); + try { + if (!Configuration.getIgnoreClassesOptions() + .matchesClassGen(this.classStorage, classGen)) { + break; + } + } catch (ClassCastException classCastException) { + Log.error("ALLATORI INTERNAL ERROR. Class " + classGen.getClassName()); + iterator = classesByName2; + continue; + } + iterator = classesByName2; + } + int value; + Method[] methods; + for (int value2 = value = (methods = classGen.getMethods()).length - 1; + value2 >= 0; + value2 = --value) { + Method method; + if ((method = methods[value]).getCode() != null) { + vector.add(new MethodContext(classGen, method)); + } + } + } + } + + public void processText(String text) throws ObfuscationException { + try { + Vector vector; + if (this.matchesValues(vector = this.createValues())) { + throw new ObfuscationException("The jar file already contains watermark."); + } + RandomUtils.processValues(vector); + short[] values = this.createValues(text); + int value; + for (int value2 = value = vector.size() - values.length / 4; value2 > 0; value2 = value) { + value--; + vector.remove(0); + } + this.processValues(vector, values); + } catch (Exception exception) { + System.out.println( + "############### EXCEPTION (" + VersionInfo.getVersion() + ") ###############"); + exception.printStackTrace(); + System.out.println("#################################################"); + throw new ObfuscationException(("Watermarking error: " + exception.getMessage())); + } + } + + public boolean matchesInstructionTargeters(InstructionTargeter[] instructionTargeters) { + if (instructionTargeters == null) { + return true; + } + int value; + for (int value2 = value = 0; value2 < instructionTargeters.length; value2 = ++value) { + InstructionTargeter instructionTargeter; + if (!((instructionTargeter = instructionTargeters[value]) instanceof LineNumberGen) + && !(instructionTargeter instanceof LocalVariableGen)) { + return false; + } + } + return true; + } + + public boolean matchesInstructionHandle(InstructionHandle instructionHandle) { + return instructionHandle.getInstruction() instanceof SIPUSH + && instructionHandle.getInstructionHandle2() != null + && instructionHandle.getInstructionHandle2().getInstruction() instanceof SIPUSH + && instructionHandle.getInstructionHandle2().getInstructionHandle2() != null + && instructionHandle.getInstructionHandle2().getInstructionHandle2().getInstruction() + instanceof SIPUSH + && instructionHandle.getInstructionHandle2().getInstructionHandle2().getInstructionHandle2() + != null + && instructionHandle + .getInstructionHandle2() + .getInstructionHandle2() + .getInstructionHandle2() + .getInstruction() + instanceof SIPUSH + && instructionHandle + .getInstructionHandle2() + .getInstructionHandle2() + .getInstructionHandle2() + .getInstructionHandle2() + != null + && instructionHandle + .getInstructionHandle2() + .getInstructionHandle2() + .getInstructionHandle2() + .getInstructionHandle2() + .getInstruction() + instanceof POP2 + && instructionHandle + .getInstructionHandle2() + .getInstructionHandle2() + .getInstructionHandle2() + .getInstructionHandle2() + .getInstructionHandle2() + != null + && instructionHandle + .getInstructionHandle2() + .getInstructionHandle2() + .getInstructionHandle2() + .getInstructionHandle2() + .getInstructionHandle2() + .getInstruction() + instanceof POP2; + } + + public short[] createValues(String text) throws UnsupportedEncodingException { + int value; + byte[] values; + int value2 = value = (values = text.getBytes("UTF-8")).length; + while (value2 % 4 != 0) { + value2 = ++value; + } + byte[] values2 = new byte[value]; + Arrays.fill(values2, (byte) 0); + values2[0] = values[0]; + if (values.length > 1) { + values2[1] = (byte) (values2[1] | values[1] ^ values[0]); + } + int value3; + for (int value4 = value3 = 2; value4 < values.length; value4 = value3) { + byte value5 = + (byte) (values2[value3] | values[value3] ^ values[value3 - 1] ^ values[value3 - 2]); + int value6 = value3; + value3++; + values2[value6] = value5; + } + int value7; + for (int value8 = value7 = values.length; value8 < value; value8 = value7) { + byte value9 = (byte) (values2[value7] | RandomUtils.calculateCount(256)); + int value10 = value7; + value7++; + values2[value10] = value9; + } + byte[] bytes = this.watermarkKey.getBytes(); + int value11; + for (int value12 = value11 = 0; value12 < values2.length; value12 = value11) { + byte value13 = (byte) (values2[value11] ^ bytes[value11 % bytes.length]); + int value14 = value11; + value11++; + values2[value14] = value13; + } + int value15 = value; + int value16; + value2 = value16 = (int) (value * (0.666 + RandomUtils.calculateValue() / 3.0)) + 113; + while (value2 % 4 != 0) { + value2 = ++value16; + } + short[] values3; + short[] values4 = values3 = new short[value15 + value16]; + int value17 = 0; + Arrays.fill(values4, (short) 0); + for (int index = 0; value17 < values3.length; value17 = index) { + if (index < value15) { + values3[index + 2] = + (short) (values3[index + 2] | values2[index] << 8 | values2[index + 2] & 0xFF); + values3[index + 3] = + (short) (values3[index + 3] | values2[index + 1] << 8 | values2[index + 3] & 0xFF); + } else { + values3[index + 2] = + (short) (values3[index + 2] | RandomUtils.calculateCount(Integer.MAX_VALUE)); + values3[index + 3] = + (short) (values3[index + 3] | RandomUtils.calculateCount(Integer.MAX_VALUE)); + } + index += 4; + } + Hashtable hashtable = new Hashtable(); + short value18 = (short) (0 | this.watermarkKey.hashCode()); + hashtable.put(new Short(value18), ""); + int value19 = 0; + for (int value20 = value19; value20 < values3.length; value20 = value19) { + int value21 = (short) (RandomUtils.calculateCount(65536) - 32768); + for (Hashtable hashtable2 = hashtable; + hashtable2.containsKey(new Short((short) value21)); + hashtable2 = hashtable) { + value21++; + } + hashtable.put(new Short((short) value21), ""); + values3[value19] = (short) value21; + if (value19 > 3) { + values3[value19 - 3] = (short) value21; + } + value19 += 4; + } + int value22; + for (int value23 = value22 = value15 + 4 * RandomUtils.calculateCount(20); + value23 < values3.length; + value23 = value22) { + int value24 = value22 + 1; + short value25 = values3[RandomUtils.calculateCount(value15 / 4) * 4]; + short[] values5 = values3; + value22 += 4; + values5[value24] = value25; + } + int value26 = this.watermarkKey.hashCode(); + values3[values3.length - 4] = + values3[values3.length - 3] = values3[values3.length - 2] = values3[values3.length - 1] = 0; + values3[values3.length - 4] = (short) (values3[values3.length - 4] | value26); + values3[values3.length - 3] = (short) (values3[values3.length - 3] | value26 >> 16); + values3[values3.length - 2] = (short) (values3[values3.length - 2] | values3[0]); + values3[values3.length - 1] = (short) (values3[values3.length - 1] | values.length); + int value27; + for (int value28 = value27 = 0; value28 < values3.length; value28 = value27) { + short value29 = values3[value27]; + short value30 = values3[value27 + 1]; + short value31 = values3[value27 + 2]; + short value32 = values3[value27 + 3]; + values3[value27] = values3[value27 + 1] = values3[value27 + 2] = values3[value27 + 3] = 0; + values3[value27] = (short) (values3[value27] | value29 ^ value30 ^ value31); + values3[value27 + 1] = (short) (values3[value27 + 1] | value30 ^ value31 ^ value32); + values3[value27 + 2] = (short) (values3[value27 + 2] | value29 ^ value31 ^ value32); + short value33 = (short) (values3[value27 + 3] | value29 ^ value30 ^ value32); + int value34 = value27 + 3; + short[] values6 = values3; + value27 += 4; + values6[value34] = value33; + } + return values3; + } + + public String createText() throws ObfuscationException { + try { + return this.createText(this.createValues(this.createValues())); + } catch (Exception exception) { + throw new ObfuscationException("Cannot extract watermark."); + } + } + + public WatermarkProcessor(ClassStorage classStorage2, String watermarkKey) { + super(); + this.classStorage = classStorage2; + this.watermarkKey = watermarkKey; + Method.setComparator(MethodComparator.getMethodComparator()); + } +} diff --git a/src/main/java/com/allatori/wtk/WTKObfuscator.java b/src/main/java/com/allatori/wtk/WTKObfuscator.java new file mode 100644 index 0000000..30af1aa --- /dev/null +++ b/src/main/java/com/allatori/wtk/WTKObfuscator.java @@ -0,0 +1,89 @@ +package com.allatori.wtk; + +import com.allatori.Obfuscate; +import com.allatori.config.Configuration; +import com.allatori.config.ConfigurationException; +import com.allatori.engine.ObfuscationException; +import com.allatori.util.FileUtils; +import com.allatori.util.Log; +import com.sun.kvem.environment.Obfuscator; +import java.io.File; +import java.io.IOException; +import java.util.StringTokenizer; + +public class WTKObfuscator implements Obfuscator { + + public String configurationFileName; + + public WTKObfuscator() { + super(); + this.configurationFileName = "allatori.xml"; + } + + public void createScriptFile(File file, File file2) {} + + public void run( + File file, String text, String text2, String text3, String text4, String text5, String text6) + throws IOException, ConfigurationException, ObfuscationException, ClassNotFoundException { + String text7; + if (!text4.endsWith("/") && !text4.endsWith("\\")) { + text7 = "" + text4 + "/" + this.configurationFileName; + } else { + text7 = "" + text4 + this.configurationFileName; + } + File file2; + File file3; + if ((file2 = new File(text7)).exists() && !file2.canWrite()) { + Log.info2("Using the existing configuration file."); + file3 = file2; + } else { + String text8 = this.createText(file, text, text2, text3, text4, text5, text6); + try { + FileUtils.processText(file2, "UTF-8", text8); + } catch (Exception exception) { + exception.printStackTrace(); + throw new IOException(); + } + file3 = file2; + } + Configuration.processText(file3.getPath()); + Obfuscate.runObfuscation(); + Configuration.update(); + } + + public String createText( + File file, + String text, + String text2, + String text3, + String text4, + String text5, + String text6) { + StringBuffer stringBuffer; + (stringBuffer = new StringBuffer()).append("\n"); + stringBuffer.append(" \n"); + stringBuffer.append(" \n"); + stringBuffer.append(" \n\n"); + stringBuffer.append(" \n"); + StringTokenizer stringTokenizer = + new StringTokenizer(text5, System.getProperty("path.separator")); + StringTokenizer stringTokenizer2 = stringTokenizer; + while (stringTokenizer2.hasMoreTokens()) { + stringTokenizer2 = stringTokenizer; + String text7 = stringTokenizer.nextToken(); + stringBuffer.append(" \n"); + } + stringBuffer.append(" \n\n"); + stringBuffer.append(" \n"); + stringBuffer.append( + " \n"); + stringBuffer.append(" \n\n"); + stringBuffer.append(" \n"); + stringBuffer.append(" \n"); + stringBuffer.append(" \n"); + stringBuffer.append(" \n"); + stringBuffer.append(" \n"); + stringBuffer.append("\n"); + return stringBuffer.toString(); + } +} diff --git a/src/main/resources/META-INF/MANIFEST.MF b/src/main/resources/META-INF/MANIFEST.MF new file mode 100644 index 0000000..c21aa5b --- /dev/null +++ b/src/main/resources/META-INF/MANIFEST.MF @@ -0,0 +1,12 @@ +Manifest-Version: 1.0 +Implementation-Title: OpenAllatori +Implementation-Version: 9.9 +Main-Class: com.allatori.Obfuscate +Bundle-ManifestVersion: 2 +Bundle-Name: OpenAllatori Builder +Bundle-SymbolicName: com.allatori.eclipse;singleton:=true +Bundle-Version: 9.9 +Bundle-RequiredExecutionEnvironment: JavaSE-17 +Require-Bundle: org.eclipse.core.resources,org.eclipse.core.runtime,or + g.eclipse.core.commands,org.eclipse.jface,org.eclipse.ui,org.eclipse. + core.expressions,org.eclipse.jdt.core diff --git a/src/main/resources/plugin.xml b/src/main/resources/plugin.xml new file mode 100644 index 0000000..2360db7 --- /dev/null +++ b/src/main/resources/plugin.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/wtkApi/java/com/sun/kvem/environment/Obfuscator.java b/src/wtkApi/java/com/sun/kvem/environment/Obfuscator.java new file mode 100644 index 0000000..a0cf97f --- /dev/null +++ b/src/wtkApi/java/com/sun/kvem/environment/Obfuscator.java @@ -0,0 +1,20 @@ +package com.sun.kvem.environment; + +import java.io.File; +import java.io.IOException; + +/** Compile-only contract of the legacy Sun Wireless Toolkit integration. */ +public interface Obfuscator { + + void createScriptFile(File outputDirectory, File inputJar) throws IOException; + + void run( + File outputJar, + String projectName, + String className, + String inputJar, + String projectDirectory, + String classPath, + String arguments) + throws Exception; +}