├── .github └── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── .gitignore ├── .gitmodules ├── .idea ├── $CACHE_FILE$ ├── codeStyles │ ├── Project.xml │ └── codeStyleConfig.xml ├── misc.xml └── vcs.xml ├── .travis.yml ├── LICENSE.COMMERCIAL ├── LICENSE.GPL ├── README.md ├── build.gradle ├── demoapp ├── build.gradle ├── dumpSmali.sh ├── resources │ └── org │ │ └── cf │ │ └── demosmali │ │ ├── Base64.smali │ │ ├── Main.smali │ │ └── TestExceptionHandling.smali └── src │ └── main │ └── java │ └── org │ └── cf │ ├── demoapp │ ├── Main.java │ └── java_io_PrintStream_println.java │ └── demosmali │ ├── Base64.java │ ├── Main.java │ └── TestExceptionHandling.java ├── dictionary.txt ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── ideas.txt ├── sdbg ├── README.md ├── build.gradle ├── resources │ └── Test.smali └── src │ └── main │ ├── java │ └── org │ │ └── cf │ │ └── sdbg │ │ ├── Initialize.kt │ │ ├── Main.kt │ │ ├── SmaliWriting.kt │ │ └── command │ │ ├── BreakCommand.kt │ │ ├── ClearScreenCommand.kt │ │ ├── CliCommands.kt │ │ ├── ContinueCommand.kt │ │ ├── DebuggerCommand.kt │ │ ├── InfoCommand.kt │ │ ├── ListCommand.kt │ │ ├── NextCommand.kt │ │ ├── PrintCommand.kt │ │ ├── StepCommand.kt │ │ └── WhereCommand.kt │ └── resources │ └── logback.xml ├── settings.gradle ├── simplify ├── .gitignore ├── ObfuscatedApp │ ├── .gitignore │ ├── .idea │ │ ├── caches │ │ │ └── gradle_models.ser │ │ ├── codeStyles │ │ │ ├── Project.xml │ │ │ └── codeStyleConfig.xml │ │ ├── copyright │ │ │ └── profiles_settings.xml │ │ ├── markdown-navigator-enh.xml │ │ ├── markdown-navigator.xml │ │ ├── misc.xml │ │ └── vcs.xml │ ├── README.md │ ├── app │ │ ├── .gitignore │ │ ├── build.gradle │ │ ├── proguard-rules.pro │ │ └── src │ │ │ ├── androidTest │ │ │ └── java │ │ │ │ └── org │ │ │ │ └── cf │ │ │ │ └── obfuscated │ │ │ │ └── ApplicationTest.java │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ └── org │ │ │ │ └── cf │ │ │ │ ├── crypto │ │ │ │ ├── AesCbcWithIntegrity.java │ │ │ │ ├── DES.java │ │ │ │ ├── TrippleDES.java │ │ │ │ └── XORCrypt.java │ │ │ │ └── obfuscated │ │ │ │ ├── MainActivity.java │ │ │ │ ├── MathCrypt.java │ │ │ │ ├── Reflection.java │ │ │ │ ├── StringHolder.java │ │ │ │ └── WhiteNoise.java │ │ │ └── res │ │ │ ├── drawable-hdpi │ │ │ └── ic_launcher.png │ │ │ ├── drawable-mdpi │ │ │ └── ic_launcher.png │ │ │ ├── drawable-xhdpi │ │ │ └── ic_launcher.png │ │ │ ├── drawable-xxhdpi │ │ │ └── ic_launcher.png │ │ │ ├── layout │ │ │ └── activity_main.xml │ │ │ ├── menu │ │ │ └── main.xml │ │ │ ├── values-v21 │ │ │ └── styles.xml │ │ │ ├── values-w820dp │ │ │ └── dimens.xml │ │ │ └── values │ │ │ ├── dimens.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ └── settings.gradle ├── build.gradle ├── obfuscated-app.apk └── src │ ├── main │ ├── java │ │ └── org │ │ │ └── cf │ │ │ └── simplify │ │ │ ├── ConstantBuilder.java │ │ │ ├── Dependency.java │ │ │ ├── ExecutionGraphManipulator.java │ │ │ ├── Launcher.java │ │ │ ├── Main.java │ │ │ ├── Optimizer.java │ │ │ ├── SimplifyOptions.java │ │ │ ├── SimplifyOptionsParser.java │ │ │ └── strategy │ │ │ ├── ConstantPropagationStrategy.java │ │ │ ├── DeadRemovalStrategy.java │ │ │ ├── OptimizationStrategy.java │ │ │ ├── PeepholeStrategy.java │ │ │ └── UnreflectionStrategy.java │ └── resources │ │ └── logback.xml │ └── test │ ├── java │ └── org │ │ └── cf │ │ └── simplify │ │ ├── ConstantBuilderTest.java │ │ ├── ExecutionGraphManipulatorTest.java │ │ ├── LauncherTest.java │ │ ├── MainTest.java │ │ ├── OptimizerTester.java │ │ └── strategy │ │ ├── ConstantPropagationStrategyTest.java │ │ ├── DeadRemovalStrategyTest.java │ │ ├── PeepholeStrategyTest.java │ │ └── UnreflectionStrategyTest.java │ └── resources │ ├── logback-test.xml │ ├── obfuscated-example.zip │ ├── obfuscated-example │ └── org │ │ └── cf │ │ └── obfuscated │ │ ├── BuildConfig.smali │ │ ├── DESCrypt.smali │ │ ├── MainActivity.smali │ │ ├── MathCrypt.smali │ │ ├── R$anim.smali │ │ ├── R$attr.smali │ │ ├── R$bool.smali │ │ ├── R$color.smali │ │ ├── R$dimen.smali │ │ ├── R$drawable.smali │ │ ├── R$id.smali │ │ ├── R$integer.smali │ │ ├── R$layout.smali │ │ ├── R$menu.smali │ │ ├── R$string.smali │ │ ├── R$style.smali │ │ ├── R$styleable.smali │ │ ├── R.smali │ │ ├── Reflection.smali │ │ ├── StringHolder.smali │ │ ├── WhiteNoise.smali │ │ └── XORCrypt.smali │ └── smali │ ├── constant_propigation_strategy_test.smali │ ├── dead_removal_strategy_test.smali │ ├── execution_graph_manipulator_test.smali │ ├── numeric.smali │ ├── optimizer_test.smali │ ├── peephole_strategy_test.smali │ └── unreflection_strategy_test.smali └── smalivm ├── build.gradle ├── libs └── android-local.jar └── src ├── main ├── java │ └── org │ │ └── cf │ │ ├── smalivm │ │ ├── ExceptionFactory.java │ │ ├── ExceptionHandlerAddressResolver.java │ │ ├── MethodExecutor.java │ │ ├── MethodExecutorFactory.java │ │ ├── MethodReflector.java │ │ ├── NodeExecutor.java │ │ ├── NonInteractiveMethodExecutor.java │ │ ├── ObjectInstantiator.java │ │ ├── SideEffect.java │ │ ├── StaticFieldAccessor.java │ │ ├── TemplateStateFactory.java │ │ ├── VirtualMachine.java │ │ ├── VirtualMachineFactory.java │ │ ├── configuration │ │ │ ├── Configuration.java │ │ │ └── ConfigurationLoader.java │ │ ├── context │ │ │ ├── BaseState.java │ │ │ ├── CallStack.java │ │ │ ├── ClassState.java │ │ │ ├── ClonerFactory.java │ │ │ ├── ExecutionContext.java │ │ │ ├── ExecutionGraph.java │ │ │ ├── ExecutionGraphIterator.java │ │ │ ├── ExecutionGrapher.java │ │ │ ├── ExecutionNode.java │ │ │ ├── Heap.java │ │ │ ├── HeapItem.java │ │ │ ├── InstanceState.java │ │ │ ├── MethodState.java │ │ │ ├── StackTraceBuilder.java │ │ │ └── StackTraceElement.java │ │ ├── debug │ │ │ ├── Breakpoint.java │ │ │ └── Debugger.java │ │ ├── dex │ │ │ ├── ClassBuilder.java │ │ │ ├── CommonTypes.java │ │ │ ├── FrameworkJarBuilder.java │ │ │ ├── SmaliClassLoader.java │ │ │ ├── SmaliFile.java │ │ │ ├── SmaliFileFactory.java │ │ │ └── SmaliParser.java │ │ ├── emulate │ │ │ ├── EmulatedMethod.java │ │ │ ├── ExecutionContextMethod.java │ │ │ ├── MethodEmulator.java │ │ │ ├── MethodStateMethod.java │ │ │ ├── UnknownValuesMethod.java │ │ │ ├── android_text_TextUtils_isEmpty.java │ │ │ ├── java_lang_Class_forName.java │ │ │ ├── java_lang_Object_getClass.java │ │ │ ├── java_lang_reflect_Field_get.java │ │ │ └── org_cf_simplify_Utils_breakpoint.java │ │ ├── exception │ │ │ ├── MaxAddressVisitsExceededException.java │ │ │ ├── MaxCallDepthExceededException.java │ │ │ ├── MaxExecutionTimeExceededException.java │ │ │ ├── MaxMethodVisitsExceededException.java │ │ │ ├── UnhandledVirtualException.java │ │ │ └── VirtualMachineException.java │ │ ├── opcode │ │ │ ├── AGetOp.java │ │ │ ├── AGetOpFactory.java │ │ │ ├── APutOp.java │ │ │ ├── APutOpFactory.java │ │ │ ├── ArrayLengthOp.java │ │ │ ├── ArrayLengthOpFactory.java │ │ │ ├── BinaryMathOp.java │ │ │ ├── BinaryMathOpFactory.java │ │ │ ├── CheckCastOp.java │ │ │ ├── CheckCastOpFactory.java │ │ │ ├── CmpOp.java │ │ │ ├── CmpOpFactory.java │ │ │ ├── ConstOp.java │ │ │ ├── ConstOpFactory.java │ │ │ ├── ExecutionContextOp.java │ │ │ ├── FillArrayDataOp.java │ │ │ ├── FillArrayDataOpFactory.java │ │ │ ├── FillArrayDataPayloadOp.java │ │ │ ├── FillArrayDataPayloadOpFactory.java │ │ │ ├── FilledNewArrayOp.java │ │ │ ├── FilledNewArrayOpFactory.java │ │ │ ├── GotoOp.java │ │ │ ├── GotoOpFactory.java │ │ │ ├── IGetOp.java │ │ │ ├── IGetOpFactory.java │ │ │ ├── IPutOp.java │ │ │ ├── IPutOpFactory.java │ │ │ ├── IfOp.java │ │ │ ├── IfOpFactory.java │ │ │ ├── InstanceOfOp.java │ │ │ ├── InstanceOfOpFactory.java │ │ │ ├── InvokeOp.java │ │ │ ├── InvokeOpFactory.java │ │ │ ├── MethodStateOp.java │ │ │ ├── MonitorEnterOp.java │ │ │ ├── MonitorEnterOpFactory.java │ │ │ ├── MonitorExitOp.java │ │ │ ├── MonitorExitOpFactory.java │ │ │ ├── MoveOp.java │ │ │ ├── MoveOpFactory.java │ │ │ ├── NewArrayOp.java │ │ │ ├── NewArrayOpFactory.java │ │ │ ├── NewInstanceOp.java │ │ │ ├── NewInstanceOpFactory.java │ │ │ ├── NopOp.java │ │ │ ├── NopOpFactory.java │ │ │ ├── Op.java │ │ │ ├── OpCreator.java │ │ │ ├── OpFactory.java │ │ │ ├── ReturnOp.java │ │ │ ├── ReturnOpFactory.java │ │ │ ├── ReturnVoidOp.java │ │ │ ├── ReturnVoidOpFactory.java │ │ │ ├── SGetOp.java │ │ │ ├── SGetOpFactory.java │ │ │ ├── SPutOp.java │ │ │ ├── SPutOpFactory.java │ │ │ ├── SwitchOp.java │ │ │ ├── SwitchOpFactory.java │ │ │ ├── SwitchPayloadOp.java │ │ │ ├── SwitchPayloadOpFactory.java │ │ │ ├── ThrowOp.java │ │ │ ├── ThrowOpFactory.java │ │ │ ├── UnaryMathOp.java │ │ │ └── UnaryMathOpFactory.java │ │ └── type │ │ │ ├── ClassManager.java │ │ │ ├── ClassManagerFactory.java │ │ │ ├── InitializedInstance.java │ │ │ ├── Instance.java │ │ │ ├── UninitializedInstance.java │ │ │ ├── UnknownValue.java │ │ │ ├── VirtualArray.java │ │ │ ├── VirtualArrayMethod.java │ │ │ ├── VirtualClass.java │ │ │ ├── VirtualClassItem.java │ │ │ ├── VirtualField.java │ │ │ ├── VirtualMethod.java │ │ │ ├── VirtualPrimitive.java │ │ │ ├── VirtualRealMethod.java │ │ │ └── VirtualType.java │ │ └── util │ │ ├── ClassNameUtils.java │ │ ├── EnumAnalyzer.java │ │ └── Utils.java └── resources │ ├── framework │ └── android-framework.jar │ ├── framework_classes.cfg │ ├── immutable_classes.cfg │ ├── props │ └── android-27-emu │ │ ├── data │ │ └── local.prop │ │ ├── default.prop │ │ └── system │ │ ├── build.prop │ │ └── default.prop │ ├── safe_classes.cfg │ ├── safe_framework_classes.cfg │ ├── safe_methods.cfg │ └── unsafe_methods.cfg └── test ├── java └── org │ └── cf │ ├── smalivm │ ├── DataStructureBenchmark.java │ ├── ExceptionHandlerAddressResolverTest.java │ ├── MatchBenchmark.java │ ├── MethodReflectorTest.java │ ├── TemplateStateFactoryTest.java │ ├── TestExceptionHandling.java │ ├── TestFieldInheritance.java │ ├── TestMethodInheritance.java │ ├── TestSideEffects.java │ ├── TestStaticFieldAccess.java │ ├── VMState.java │ ├── VMTester.java │ ├── VirtualMachineTest.java │ ├── configuration │ │ └── ConfigurationTest.java │ ├── context │ │ ├── ExecutionGraphTest.java │ │ ├── ExecutionGrapherTest.java │ │ └── MethodStateTest.java │ ├── dex │ │ ├── ClassBuilderTest.java │ │ ├── ClassManagerTest.java │ │ ├── FrameworkJarBuilderTest.java │ │ ├── SmaliClassLoaderTest.java │ │ └── SmaliParserTest.java │ ├── emulate │ │ ├── java_lang_Class_forName_Test.java │ │ └── java_lang_reflect_Field_get_Test.java │ ├── opcode │ │ ├── AGetOpTest.java │ │ ├── APutOpTest.java │ │ ├── ArrayLengthOpTest.java │ │ ├── BinaryMathOpTest.java │ │ ├── CheckCastOpTest.java │ │ ├── CmpOpTest.java │ │ ├── ConstOpTest.java │ │ ├── FillArrayDataOpTest.java │ │ ├── FilledNewArrayTest.java │ │ ├── IGetOpTest.java │ │ ├── IPutOpTest.java │ │ ├── IfOpTest.java │ │ ├── InstanceOfOpTest.java │ │ ├── InvokeOpTest.java │ │ ├── MonitorEnterOpTest.java │ │ ├── MonitorExitOpTest.java │ │ ├── MoveOpTest.java │ │ ├── NewArrayOpTest.java │ │ ├── NewInstanceOpTest.java │ │ ├── SGetOpTest.java │ │ ├── SPutOpTest.java │ │ ├── SwitchOpTest.java │ │ ├── SwitchPayloadOpTest.java │ │ ├── ThrowOpTest.java │ │ └── UnaryMathOpTest.java │ └── type │ │ └── VirtualArrayTest.java │ └── util │ ├── ClassNameUtilsTest.java │ └── UtilsTest.java └── resources └── smali ├── class_builder ├── CircularReference1.smali ├── CircularReference2.smali ├── ComplexClass$TestEnum.smali ├── ComplexClass.smali ├── IllegalFieldModifiers.smali ├── NonExistentReference.smali ├── OverloadedFields.smali ├── SelfReference.smali ├── SimpleClass.smali ├── SimpleInterface.smali └── SuperClass.smali ├── exceptions ├── CustomException.smali └── ExceptionalCode.smali ├── execution_graph.smali ├── extends_enum.smali ├── extends_enum_obfuscated.smali ├── field_get ├── DummyChildClass.smali ├── DummyClass$DummyInnerClass.smali ├── DummyClass.java ├── DummyClass.smali ├── SamePackageClass.smali └── UnrelatedClass.smali ├── hash_code.smali ├── inheritance ├── child_class.smali ├── grandparent_class.smali ├── grandparent_interface.smali └── parent_class.smali ├── method_reflector_test.smali ├── native_method_class.smali ├── object_init ├── class_with_default_constructor.smali ├── class_without_default_constructor.smali └── class_without_default_constructor_checks_null.smali ├── ops ├── aget_test.smali ├── aput_test.smali ├── array_length_test.smali ├── binary_math_test.smali ├── check_cast_test.smali ├── class_with_static_init.smali ├── cmp_test.smali ├── const_test.smali ├── fill_array_data_test.smali ├── filled_new_array_test.smali ├── if_test.smali ├── iget_test.smali ├── instanceof_test.smali ├── invoke_direct_test.smali ├── invoke_emulated_test.smali ├── invoke_reflected_test.smali ├── invoke_static_test.smali ├── invoke_virtual_test.smali ├── iput_test.smali ├── monitor_enter_test.smali ├── monitor_exit_test.smali ├── move_test.smali ├── new_array_test.smali ├── new_instance_test.smali ├── sget_test.smali ├── sput_test.smali ├── swich_test.smali ├── throw_test.smali └── unary_math_test.smali ├── side_effects ├── no_side_effect.smali ├── side_effects_test.smali ├── strong_side_effect.smali └── weak_side_effect.smali ├── simple_loop.smali └── static_fields_test.smali /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | 5 | --- 6 | 7 | **Provide specific APK, DEX, or file hash** 8 | Please make it easy to get the _exact same_ file you're having trouble with. Please don't link to Google Play or another market since it's not always possible to get the specific version you're having trouble with. Either upload the file if possible or share the file hash if it's available on VirusTotal. 9 | 10 | **Describe the bug** 11 | Please include error logs. If the logs are mostly empty, use verbose mode. 12 | 13 | **To Reproduce** 14 | How did you run simplify exactly? 15 | 16 | **Attempted work-arounds** 17 | Did you try any work-arounds? Did you read the README? 18 | 19 | **Screenshots** 20 | If applicable, add screenshots to help explain your problem. 21 | 22 | **Additional context** 23 | Add any other context about the problem here. 24 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | 5 | --- 6 | 7 | **Is your feature request related to a problem? Please describe.** 8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 9 | 10 | **Describe the solution you'd like** 11 | A clear and concise description of what you want to happen. 12 | 13 | **Describe alternatives you've considered** 14 | A clear and concise description of any alternative solutions or features you've considered. 15 | 16 | **Additional context** 17 | Add any other context or screenshots about the feature request here. 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | todo.txt 2 | 3 | hs_err_pid* 4 | 5 | ### JetBrains IDEA IntelliJ ### 6 | # User-specific stuff 7 | .idea/**/workspace.xml 8 | .idea/**/tasks.xml 9 | .idea/**/usage.statistics.xml 10 | .idea/**/dictionaries 11 | .idea/**/shelf 12 | 13 | # Generated files 14 | .idea/**/contentModel.xml 15 | 16 | # Sensitive or high-churn files 17 | .idea/**/dataSources/ 18 | .idea/**/dataSources.ids 19 | .idea/**/dataSources.local.xml 20 | .idea/**/sqlDataSources.xml 21 | .idea/**/dynamic.xml 22 | .idea/**/uiDesigner.xml 23 | .idea/**/dbnavigator.xml 24 | 25 | # Gradle 26 | .idea/**/gradle.xml 27 | .idea/**/libraries 28 | 29 | # Gradle and Maven with auto-import 30 | .idea/artifacts 31 | .idea/compiler.xml 32 | .idea/jarRepositories.xml 33 | .idea/modules.xml 34 | .idea/*.iml 35 | .idea/modules 36 | *.iml 37 | *.ipr 38 | 39 | # File-based project format 40 | *.iws 41 | 42 | # IntelliJ 43 | out/ 44 | .idea/caches/ 45 | ### End JetBrains IDEA IntelliJ ### 46 | 47 | # Gradle 48 | build/ 49 | .gradle 50 | 51 | # Eclipse 52 | .classpath 53 | .project 54 | .settings/ 55 | 56 | # Logging 57 | log.txt 58 | bin/ 59 | 60 | # Generated Java documentation 61 | smalivm/doc 62 | simplify/doc 63 | demoapp/doc 64 | 65 | # MacOS 66 | .DS_Store 67 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "smalivm/src/main/resources/framework/smali"] 2 | path = smalivm/src/main/resources/framework/smali 3 | url = https://github.com/CalebFenton/AndroidFrameworkSmali.git 4 | -------------------------------------------------------------------------------- /.idea/$CACHE_FILE$: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 14 | 15 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | sudo: required 3 | dist: trusty 4 | jdk: 5 | - oraclejdk8 6 | env: 7 | matrix: 8 | - TERM=dumb 9 | global: 10 | - GRADLE_OPTS="-Xms128m -Xmx6g -Xss512k" 11 | - MALLOC_ARENA_MAX=2 12 | - CI_NAME=travis-ci 13 | - secure: dz8FVLtE8hXYAhrMcBoYJh6iDbfm8V231eqLF4uWVeEDptf5iEvE58YqyDp9MW/XSo2KpWHdd8CkGK/auMrr6gAOTUY4woIDncdzGcnTTQQPJXVgdXjdilEwFrzEdTR64wkusBA924u47JOQnAXQTrhD0kZYD6ckcW9Bw4gg74s= 14 | - secure: CuqvnSiDcMGB7AxaFBq82zXuh+PwZ2nfcD+Y3AI38H3Hj9EdEwqrpkSaSrxPIvoShe7YgCtUqc/ELNuU7IeocosxJP6aA3Rd5fsSc4IHbWTER0+EnqepiDaDjIttvA9WnUwSypeN5lkdaT0yqUCI1j5FuGus+o4liq7n/4IXAlw= 15 | before_install: 16 | - chmod +x gradlew 17 | - echo -n | openssl s_client -connect scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END 18 | CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca- 19 | before_script: 20 | - sudo service docker stop || true 21 | - sudo service elasticsearch stop || true 22 | - sudo service memcached stop || true 23 | - sudo service mysql stop || true 24 | - sudo service neo4j stop || true 25 | - sudo service postgresql stop || true 26 | - sudo service redis-server stop || true 27 | - sudo service rsync stop || true 28 | - sudo service x11-common stop || true 29 | - ps -e -o pid,vsz,comm= | sort -n -k 2 30 | - sudo free -m -t 31 | script: 32 | - ./gradlew test --no-daemon 33 | after_success: 34 | - "./gradlew jacocoRootReport coveralls" 35 | before_cache: 36 | - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock 37 | - rm -fr $HOME/.gradle/caches/*/plugin-resolution/ 38 | cache: 39 | directories: 40 | - $HOME/.gradle/caches/ 41 | - $HOME/.gradle/wrapper/ 42 | addons: 43 | coverity_scan: 44 | project: 45 | name: CalebFenton/simplify 46 | description: Build submitted via Travis CI 47 | notification_email: calebjfenton@gmail.com 48 | build_command_prepend: "./gradlew clean" 49 | build_command: "./gradlew build" 50 | branch_pattern: coverity_scan 51 | -------------------------------------------------------------------------------- /LICENSE.COMMERCIAL: -------------------------------------------------------------------------------- 1 | The commercial license of Simplify and smalivm allows you to use them in commercial products. 2 | 3 | - The commercial license is perpetual and royalty-free. 4 | - You have the right to distribute the binary and modifications. 5 | - No source code redistribution is allowed in any way. 6 | 7 | Contact rednaga@protonmail.com for further information. -------------------------------------------------------------------------------- /demoapp/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | id 'application' 4 | } 5 | 6 | project.version = '1.0.0' 7 | mainClassName = 'org.cf.demoapp.Main' 8 | 9 | dependencies { 10 | implementation project(':smalivm') 11 | implementation depends.slf4j_api 12 | implementation depends.slf4j_nop 13 | } 14 | 15 | task fatJar(type: Jar) { 16 | from sourceSets.main.output 17 | from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } } 18 | 19 | manifest { 20 | attributes('Main-Class': mainClassName) 21 | } 22 | 23 | doLast { 24 | if (!System.getProperty('os.name').toLowerCase().contains('windows')) { 25 | ant.symlink(link: file("${destinationDirectory.get()}/demoapp.jar"), resource: archiveFile.get(), overwrite: true) 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /demoapp/dumpSmali.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | echo "Compiling Java classes to Dalvik executable" 3 | dx --dex --no-strict --output=build/classes.dex build/classes/java/main/org/cf/demosmali 4 | 5 | echo "Disassembling Dalvik executable" 6 | baksmali disassemble --sequential-labels --code-offsets --use-locals build/classes.dex -o resources/ 7 | -------------------------------------------------------------------------------- /demoapp/src/main/java/org/cf/demoapp/java_io_PrintStream_println.java: -------------------------------------------------------------------------------- 1 | package org.cf.demoapp; 2 | 3 | import org.cf.smalivm.SideEffect; 4 | import org.cf.smalivm.VirtualMachine; 5 | import org.cf.smalivm.context.HeapItem; 6 | import org.cf.smalivm.context.MethodState; 7 | import org.cf.smalivm.emulate.MethodStateMethod; 8 | import org.cf.smalivm.emulate.UnknownValuesMethod; 9 | import org.cf.smalivm.opcode.Op; 10 | 11 | public class java_io_PrintStream_println extends MethodStateMethod implements UnknownValuesMethod { 12 | public java_io_PrintStream_println() { 13 | super(); 14 | // Writing bytes over any kind of IO affects state outside of the VM. 15 | // Set the side effect level so the optimizer knows not to remove this method call. 16 | level = SideEffect.Level.STRONG; 17 | } 18 | 19 | @Override 20 | protected void execute(VirtualMachine vm, Op op, MethodState mState) { 21 | // This is a virtual method, so register 0 contains a reference to an instance of Ljava/io/PrintStream; 22 | // Register 1 should have the string to print. 23 | HeapItem item = mState.peekParameter(1); 24 | String value = (String) item.getValue(); 25 | System.out.println(value); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /demoapp/src/main/java/org/cf/demosmali/Main.java: -------------------------------------------------------------------------------- 1 | package org.cf.demosmali; 2 | 3 | public class Main { 4 | 5 | public static void helloWorld() { 6 | byte[] data = new byte[] { 97, 71, 86, 115, 98, 71, 56, 115, 100, 50, 57, 121, 98, 71, 81, 104 }; 7 | String output = new String(Base64.decode(data)); 8 | 9 | System.out.println("helloWorld(): " + output); 10 | } 11 | 12 | public static void main(String[] args) { 13 | helloWorld(); 14 | stringBuilder(); 15 | } 16 | 17 | public static void stringBuilder() { 18 | StringBuilder sb = new StringBuilder(); 19 | sb.append(Integer.parseInt("1")); 20 | sb.append(Long.parseLong("2")); 21 | sb.append('3'); 22 | sb.append("abc"); 23 | 24 | System.out.println("stringBuilder(): " + sb.toString()); 25 | } 26 | 27 | @SuppressWarnings("unused") 28 | private static void printParameter(int param) { 29 | System.out.println("printParameter(), param = " + param); 30 | } 31 | 32 | @SuppressWarnings("unused") 33 | private int parameterLogic(int param) { 34 | int x = 5; 35 | if (param == 10) { 36 | x = 10; 37 | } 38 | 39 | System.out.println("parameterLogic(), x = " + x); 40 | 41 | return x; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /dictionary.txt: -------------------------------------------------------------------------------- 1 | payload 2 | smali 3 | dalvik 4 | thyroid 5 | unhandled 6 | refactor 7 | nerd 8 | bytecode 9 | gradle 10 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.daemon=true 2 | org.gradle.parallel=true 3 | org.gradle.caching=true 4 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CalebFenton/simplify/29fb25d624aecf0b075dea5c6029b2541474ddfe/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sat Jan 25 16:14:08 PST 2020 2 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip 3 | distributionBase=GRADLE_USER_HOME 4 | distributionPath=wrapper/dists 5 | zipStorePath=wrapper/dists 6 | zipStoreBase=GRADLE_USER_HOME 7 | -------------------------------------------------------------------------------- /sdbg/README.md: -------------------------------------------------------------------------------- 1 | # Smali Debugger (sdbg) 2 | 3 | Sdbg is a Smali debugger powered by SmaliVM. The command line interface is loosely based on [gdb](https://sourceware.org/gdb/current/onlinedocs/gdb/). All of the commands are documented within the app. 4 | 5 | [![demo](https://asciinema.org/a/327115.svg)](https://asciinema.org/a/327115) 6 | 7 | Right now, it's only an experiment, so if you have feature suggestions, feel free to create an issue or pull request. 8 | 9 | Since sdbg is powered by SmaliVM, it has all of its strengths and weaknesses. It can handle unknown values and parameters by taking every execution path, which is cool. But it's also possible to get stuck in infinite loops and debugging multiple execution paths is tricky. 10 | 11 | ## Building 12 | 13 | From the root of this repository: 14 | 15 | ```bash 16 | ./gradlew :sdbg:fatjar 17 | ``` 18 | 19 | The full jar will be in `sdbg/build/libs/`. 20 | 21 | ## Usage 22 | 23 | ```plaintext 24 | Usage:
[-hVv] input-path method-signature 25 | Smali DeBuGger (SDBG) 26 | input-path Input directory containing Smali 27 | method-signature Method signature to execute 28 | -h, --help Show this help message and exit. 29 | -v, --verbose Specify multiple -v options to increase verbosity. 30 | For example, `-v -v -v` or `-vvv` 31 | -V, --version Print version information and exit. 32 | ``` 33 | 34 | ```plaintext 35 | Commands: 36 | help Displays help information about the specified command 37 | cls, clear Clears the screen 38 | list, l List source code 39 | where, w Shows current instruction index and which function you are in 40 | step, s Step to next line of code including stepping into methods 41 | next, n Execute next line of code without entering methods 42 | info, i List information about target 43 | print, p Print value stored in variable or field 44 | break, b Suspend program at specified function, instruction index, or 45 | index offset 46 | continue, c Continue executing until next break point 47 | ``` 48 | -------------------------------------------------------------------------------- /sdbg/build.gradle: -------------------------------------------------------------------------------- 1 | version = '0.1.0' 2 | mainClassName = 'org.cf.sdbg.Main' 3 | 4 | dependencies { 5 | implementation project(':smalivm') 6 | implementation depends.commons_cli 7 | implementation group: 'info.picocli', name: 'picocli-shell-jline3', version: '4.1.4' 8 | implementation group: 'info.picocli', name: 'picocli-codegen', version: '4.1.4' 9 | implementation group: 'org.fusesource.jansi', name: 'jansi', version: '1.18' 10 | implementation depends.slf4j_api 11 | implementation group: 'ch.qos.logback', name: 'logback-core', version: '1.2.3' 12 | implementation group: 'ch.qos.logback', name: 'logback-classic', version: '1.2.3' 13 | 14 | testImplementation project(':smalivm').sourceSets.test.output 15 | testImplementation project(':smalivm').sourceSets.test.resources 16 | testImplementation depends.mockito 17 | testImplementation depends.junit_compile 18 | testRuntimeOnly depends.junit_engine 19 | testRuntimeOnly depends.junit_runner 20 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8" 21 | } 22 | 23 | compileKotlin { 24 | kotlinOptions { 25 | jvmTarget = JavaVersion.VERSION_1_8 26 | } 27 | } 28 | compileTestKotlin { 29 | kotlinOptions { 30 | jvmTarget = JavaVersion.VERSION_1_8 31 | } 32 | } 33 | 34 | test.dependsOn project(':smalivm').tasks.getByName('testClasses') 35 | 36 | task fatJar(type: Jar, dependsOn: ':smalivm:fatJar') { 37 | manifest { 38 | attributes('Main-Class': mainClassName) 39 | } 40 | from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } } 41 | with jar 42 | 43 | doLast { 44 | if (!System.getProperty('os.name').toLowerCase().contains('windows')) { 45 | ant.symlink(link: file("${destinationDirectory.get()}/sdbg.jar"), resource: archiveFile.get(), overwrite: true) 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /sdbg/resources/Test.smali: -------------------------------------------------------------------------------- 1 | .class LTest; 2 | .super Ljava/lang/Object; 3 | 4 | 5 | .method constructor ()V 6 | .locals 0 7 | .prologue 8 | .line 1 9 | invoke-direct {p0}, Ljava/lang/Object;->()V 10 | return-void 11 | .end method 12 | 13 | .method public static addNumbers()V 14 | .locals 2 15 | const/4 v0, 0x2 16 | const/4 v1, 0x3 17 | add-int v0, v0, v1 18 | add-int v0, v0, v1 19 | invoke-static {v0, v1}, LTest;->addParameters(II)I 20 | move-result v0 21 | return-void 22 | .end method 23 | 24 | .method public static addParameters(II)I 25 | .locals 0 26 | add-int p0, p0, p1 27 | return p0 28 | .end method 29 | 30 | .method public static multiPath()V 31 | .locals 2 32 | 33 | const/4 v0, 0x1 34 | const/4 v1, 0x2 35 | if-eq v0, v1, :end 36 | 37 | add-int v0, v0, v1 38 | 39 | :end 40 | return-void 41 | .end method 42 | 43 | .method public static main([Ljava/lang/String;)V 44 | .locals 2 45 | 46 | .prologue 47 | .line 3 48 | sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream; 49 | const-string v1, "hello,world!" 50 | invoke-virtual {v0, v1}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V 51 | 52 | .line 4 53 | return-void 54 | .end method 55 | -------------------------------------------------------------------------------- /sdbg/src/main/java/org/cf/sdbg/Initialize.kt: -------------------------------------------------------------------------------- 1 | package org.cf.sdbg 2 | 3 | import ch.qos.logback.classic.Level 4 | import ch.qos.logback.classic.Logger 5 | import org.cf.smalivm.debug.Debugger 6 | import org.slf4j.LoggerFactory 7 | import picocli.CommandLine 8 | import java.io.File 9 | import java.util.concurrent.Callable 10 | 11 | @CommandLine.Command(mixinStandardHelpOptions = true, version = [Main.version], 12 | description = ["Smali DeBuGger (SDBG)"]) 13 | internal class Initialize : Callable { 14 | @CommandLine.Parameters(index = "0", paramLabel = "input-path", arity = "1", 15 | description = ["Input directory containing Smali"]) 16 | private lateinit var inputFile: File 17 | @CommandLine.Parameters(index = "1", paramLabel = "method-signature", arity = "1", 18 | description = ["Method signature to execute"]) 19 | private lateinit var methodSignature: String 20 | 21 | @CommandLine.Option(names = ["-v", "--verbose"], 22 | description = ["Specify multiple -v options to increase verbosity.", "For example, `-v -v -v` or `-vvv`"]) 23 | private var verbosity = BooleanArray(0) 24 | 25 | private fun setLogLevel(verbosity: Int) { 26 | val rootLogger = LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME) as Logger 27 | when (verbosity) { 28 | 0 -> { rootLogger.level = Level.OFF } 29 | 1 -> { rootLogger.level = Level.INFO } 30 | 2 -> { rootLogger.level = Level.DEBUG } 31 | 3 -> { rootLogger.level = Level.TRACE } 32 | } 33 | } 34 | 35 | override fun call(): Int { 36 | setLogLevel(verbosity.size) 37 | println("Starting debugger for $methodSignature from $inputFile") 38 | Main.debugger = Debugger(inputFile, methodSignature) 39 | return 1 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /sdbg/src/main/java/org/cf/sdbg/command/ClearScreenCommand.kt: -------------------------------------------------------------------------------- 1 | package org.cf.sdbg.command 2 | 3 | import picocli.CommandLine 4 | import picocli.CommandLine.ParentCommand 5 | import java.io.IOException 6 | import java.util.concurrent.Callable 7 | 8 | @CommandLine.Command(name = "cls", aliases = ["clear"], mixinStandardHelpOptions = true, 9 | description = ["Clears the screen"]) 10 | class ClearScreenCommand : Runnable { 11 | @ParentCommand 12 | lateinit var parent: CliCommands 13 | 14 | @Throws(IOException::class) 15 | override fun run() { 16 | parent.reader.clearScreen() 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /sdbg/src/main/java/org/cf/sdbg/command/CliCommands.kt: -------------------------------------------------------------------------------- 1 | package org.cf.sdbg.command 2 | 3 | import org.cf.sdbg.Main 4 | import org.jline.reader.LineReader 5 | import org.jline.reader.impl.LineReaderImpl 6 | import picocli.CommandLine 7 | import java.io.PrintWriter 8 | 9 | @CommandLine.Command(name = "", version = [Main.version], footer = ["", "Press Ctl-D to exit."], 10 | description = [ 11 | "Smali DeBuGger (SDBG) Hit @|magenta |@ to see available commands.", 12 | "Type `@|bold,yellow keymap ^[s tailtip-toggle|@`, then hit @|magenta ALT-S|@ to toggle tailtips.", 13 | "" 14 | ], 15 | subcommands = [ 16 | CommandLine.HelpCommand::class, 17 | ClearScreenCommand::class, 18 | ListCommand::class, 19 | WhereCommand::class, 20 | StepCommand::class, 21 | NextCommand::class, 22 | InfoCommand::class, 23 | PrintCommand::class, 24 | BreakCommand::class, 25 | ContinueCommand::class 26 | ]) 27 | class CliCommands : Runnable { 28 | lateinit var reader: LineReaderImpl 29 | lateinit var out: PrintWriter 30 | fun setReader(reader: LineReader) { 31 | this.reader = reader as LineReaderImpl 32 | out = reader.terminal.writer() 33 | 34 | } 35 | 36 | override fun run() { 37 | out.println(CommandLine(this).usageMessage) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /sdbg/src/main/java/org/cf/sdbg/command/ContinueCommand.kt: -------------------------------------------------------------------------------- 1 | package org.cf.sdbg.command 2 | 3 | import picocli.CommandLine 4 | import picocli.CommandLine.ParentCommand 5 | 6 | @CommandLine.Command(name = "continue", aliases = ["c"], mixinStandardHelpOptions = true, 7 | description = ["Continue executing until next break point"]) 8 | class ContinueCommand : DebuggerCommand() { 9 | @ParentCommand 10 | lateinit var parent: CliCommands 11 | @CommandLine.Parameters(index = "0", arity = "0..1", paramLabel = "number", 12 | description = ["Ignore this many breakpoints. Useful when inside a loop."]) 13 | var target: String? = null 14 | 15 | override fun run() { 16 | var number = target?.toIntOrNull() ?: 0 17 | while (number >= 0) { 18 | debugger.run() 19 | if (debugger.isFinished) { 20 | parent.out.println("execution finished") 21 | break 22 | } else if (debugger.isAtBreakpoint) { 23 | parent.out.println("hit breakpoint " + number) 24 | number-- 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /sdbg/src/main/java/org/cf/sdbg/command/DebuggerCommand.kt: -------------------------------------------------------------------------------- 1 | package org.cf.sdbg.command 2 | 3 | import org.cf.sdbg.Main 4 | import org.cf.smalivm.debug.Debugger 5 | 6 | open class DebuggerCommand : Runnable { 7 | protected val debugger: Debugger by lazy { Main.debugger } 8 | 9 | override fun run() { 10 | TODO("not implemented; that's a 50 DKP MINUS for not implementing me!") 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /sdbg/src/main/java/org/cf/sdbg/command/NextCommand.kt: -------------------------------------------------------------------------------- 1 | package org.cf.sdbg.command 2 | 3 | import org.cf.smalivm.exception.UnhandledVirtualException 4 | import picocli.CommandLine 5 | import picocli.CommandLine.ParentCommand 6 | 7 | @CommandLine.Command(name = "next", aliases = ["n"], mixinStandardHelpOptions = true, 8 | description = ["Execute next line of code without entering methods"]) 9 | class NextCommand : DebuggerCommand() { 10 | @ParentCommand 11 | lateinit var parent: CliCommands 12 | 13 | override fun run() { 14 | try { 15 | debugger.currentIndex 16 | val currentOp = debugger.currentOp 17 | parent.out.println("${debugger.currentIndex}:>\t${currentOp}") 18 | val node = debugger.step(false) 19 | node ?: parent.out.println("execution terminated") 20 | } catch (e: UnhandledVirtualException) { 21 | e.printStackTrace(parent.out) 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /sdbg/src/main/java/org/cf/sdbg/command/StepCommand.kt: -------------------------------------------------------------------------------- 1 | package org.cf.sdbg.command 2 | 3 | import org.cf.smalivm.exception.UnhandledVirtualException 4 | import picocli.CommandLine 5 | import picocli.CommandLine.ParentCommand 6 | 7 | @CommandLine.Command(name = "step", aliases = ["s"], mixinStandardHelpOptions = true, 8 | description = ["Step to next line of code including stepping into methods"]) 9 | class StepCommand : DebuggerCommand() { 10 | @ParentCommand 11 | lateinit var parent: CliCommands 12 | 13 | override fun run() { 14 | try { 15 | val currentOp = debugger.currentOp 16 | parent.out.println("${debugger.currentIndex}:>\t${currentOp}") 17 | val node = debugger.step() 18 | node ?: parent.out.println("execution finished") 19 | } catch (e: UnhandledVirtualException) { 20 | e.printStackTrace(parent.out) 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /sdbg/src/main/java/org/cf/sdbg/command/WhereCommand.kt: -------------------------------------------------------------------------------- 1 | package org.cf.sdbg.command 2 | 3 | import picocli.CommandLine 4 | import picocli.CommandLine.ParentCommand 5 | 6 | @CommandLine.Command(name = "where", aliases = ["w"], mixinStandardHelpOptions = true, 7 | description = ["Shows current instruction index and which function you are in"]) 8 | class WhereCommand : DebuggerCommand() { 9 | @ParentCommand 10 | lateinit var parent: CliCommands 11 | 12 | override fun run() { 13 | parent.out.println("#${debugger.currentIndex} in ${debugger.currentMethodSignature}") 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /sdbg/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | %d{HH:mm:ss.SSS} %-5level %-12logger{12} - %msg%n 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include 'smalivm', 'simplify', 'demoapp', 'sdbg' 2 | -------------------------------------------------------------------------------- /simplify/.gitignore: -------------------------------------------------------------------------------- 1 | sandbox 2 | 3 | *_simple.dex 4 | *_simple.apk 5 | -------------------------------------------------------------------------------- /simplify/ObfuscatedApp/.gitignore: -------------------------------------------------------------------------------- 1 | ### Android template 2 | # Built application files 3 | *.apk 4 | *.ap_ 5 | 6 | # Files for the ART/Dalvik VM 7 | *.dex 8 | 9 | # Java class files 10 | *.class 11 | 12 | # Generated files 13 | bin/ 14 | gen/ 15 | out/ 16 | 17 | # Gradle files 18 | .gradle/ 19 | build/ 20 | 21 | # Local configuration file (sdk path, etc) 22 | local.properties 23 | 24 | # Proguard folder generated by Eclipse 25 | proguard/ 26 | 27 | # Log Files 28 | *.log 29 | 30 | # Android Studio Navigation editor temp files 31 | .navigation/ 32 | 33 | # Android Studio captures folder 34 | captures/ 35 | 36 | ### JetBrains IDEA IntelliJ ### 37 | # User-specific stuff 38 | .idea/**/workspace.xml 39 | .idea/**/tasks.xml 40 | .idea/**/usage.statistics.xml 41 | .idea/**/dictionaries 42 | .idea/**/shelf 43 | 44 | # Generated files 45 | .idea/**/contentModel.xml 46 | 47 | # Sensitive or high-churn files 48 | .idea/**/dataSources/ 49 | .idea/**/dataSources.ids 50 | .idea/**/dataSources.local.xml 51 | .idea/**/sqlDataSources.xml 52 | .idea/**/dynamic.xml 53 | .idea/**/uiDesigner.xml 54 | .idea/**/dbnavigator.xml 55 | 56 | # Gradle 57 | .idea/**/gradle.xml 58 | .idea/**/libraries 59 | 60 | # Gradle and Maven with auto-import 61 | .idea/artifacts 62 | .idea/compiler.xml 63 | .idea/jarRepositories.xml 64 | .idea/modules.xml 65 | .idea/*.iml 66 | .idea/modules 67 | *.iml 68 | *.ipr 69 | 70 | # File-based project format 71 | *.iws 72 | 73 | # IntelliJ 74 | out/ 75 | .idea/caches/ 76 | ### End JetBrains IDEA IntelliJ ### 77 | -------------------------------------------------------------------------------- /simplify/ObfuscatedApp/.idea/caches/gradle_models.ser: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CalebFenton/simplify/29fb25d624aecf0b075dea5c6029b2541474ddfe/simplify/ObfuscatedApp/.idea/caches/gradle_models.ser -------------------------------------------------------------------------------- /simplify/ObfuscatedApp/.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /simplify/ObfuscatedApp/.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /simplify/ObfuscatedApp/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /simplify/ObfuscatedApp/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /simplify/ObfuscatedApp/app/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | jcenter() 4 | google() 5 | } 6 | dependencies { 7 | classpath 'com.android.tools.build:gradle:4.0.1' 8 | } 9 | } 10 | apply plugin: 'com.android.application' 11 | 12 | repositories { 13 | jcenter() 14 | maven { 15 | url 'https://maven.google.com/' 16 | name 'Google' 17 | } 18 | } 19 | 20 | android { 21 | compileSdkVersion 30 22 | buildToolsVersion "29.0.2" 23 | 24 | defaultConfig { 25 | applicationId "org.cf.obfuscated" 26 | minSdkVersion 14 27 | targetSdkVersion 30 28 | versionCode 1 29 | versionName "1.0" 30 | } 31 | buildTypes { 32 | release { 33 | minifyEnabled false 34 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 35 | } 36 | } 37 | } 38 | 39 | dependencies { 40 | implementation fileTree(include: ['*.jar'], dir: 'libs') 41 | implementation 'androidx.appcompat:appcompat:1.2.0' 42 | } 43 | -------------------------------------------------------------------------------- /simplify/ObfuscatedApp/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/cfenton/android/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /simplify/ObfuscatedApp/app/src/androidTest/java/org/cf/obfuscated/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package org.cf.obfuscated; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /simplify/ObfuscatedApp/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /simplify/ObfuscatedApp/app/src/main/java/org/cf/crypto/TrippleDES.java: -------------------------------------------------------------------------------- 1 | package org.cf.crypto; 2 | 3 | import android.util.Base64; 4 | 5 | import java.security.MessageDigest; 6 | import java.util.Arrays; 7 | 8 | import javax.crypto.Cipher; 9 | import javax.crypto.SecretKey; 10 | import javax.crypto.spec.SecretKeySpec; 11 | 12 | public class TrippleDES { 13 | private static String ALGO = "DESede/ECB/PKCS7Padding"; 14 | 15 | public static String encrypt(String message, String secretKey) throws Exception { 16 | Cipher cipher = Cipher.getInstance(ALGO); 17 | cipher.init(Cipher.ENCRYPT_MODE, getSecreteKey(secretKey)); 18 | byte[] plainTextBytes = message.getBytes("UTF-8"); 19 | byte[] buf = cipher.doFinal(plainTextBytes); 20 | byte[] base64Bytes = Base64.encode(buf, Base64.DEFAULT); 21 | String base64EncryptedString = new String(base64Bytes); 22 | 23 | return base64EncryptedString; 24 | } 25 | 26 | public static String decrypt(String encryptedText, String secretKey) throws Exception { 27 | byte[] message = Base64.decode(encryptedText.getBytes(), Base64.DEFAULT); 28 | Cipher decipher = Cipher.getInstance(ALGO); 29 | decipher.init(Cipher.DECRYPT_MODE, getSecreteKey(secretKey)); 30 | byte[] plainText = decipher.doFinal(message); 31 | 32 | return new String(plainText, "UTF-8"); 33 | } 34 | 35 | public static SecretKey getSecreteKey(String secretKey) throws Exception { 36 | MessageDigest md = MessageDigest.getInstance("SHA-1"); 37 | byte[] digestOfPassword = md.digest(secretKey.getBytes("UTF-8")); 38 | byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24); 39 | SecretKey key = new SecretKeySpec(keyBytes, "DESede"); 40 | 41 | return key; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /simplify/ObfuscatedApp/app/src/main/java/org/cf/crypto/XORCrypt.java: -------------------------------------------------------------------------------- 1 | package org.cf.crypto; 2 | 3 | public class XORCrypt { 4 | 5 | public static String encode(String data, String key) { 6 | byte[] dataBytes = data.getBytes(); 7 | byte[] keyBytes = key.getBytes(); 8 | 9 | int keyPointer = 0; 10 | for (int i = 0; i < dataBytes.length; i++) { 11 | dataBytes[i] ^= keyBytes[keyPointer]; 12 | keyPointer += dataBytes[i]; 13 | keyPointer %= keyBytes.length; 14 | } 15 | 16 | return new String(dataBytes); 17 | } 18 | 19 | public static String decode(String data, String key) { 20 | byte[] dataBytes = data.getBytes(); 21 | byte[] keyBytes = key.getBytes(); 22 | 23 | int keyPointer = 0; 24 | byte keyPointerAdd = 0; 25 | for (int i = 0; i < dataBytes.length; i++) { 26 | keyPointerAdd = dataBytes[i]; 27 | dataBytes[i] ^= keyBytes[keyPointer]; 28 | keyPointer += keyPointerAdd; 29 | keyPointer %= keyBytes.length; 30 | } 31 | 32 | return new String(dataBytes); 33 | } 34 | 35 | public static void main(String[] argv) { 36 | // String key = StringHolder.xorKey; 37 | // System.out.println("key = " + key); 38 | // String encoded = encode("java.lang.Integer", key); 39 | // System.out.println(Arrays.toString(encoded.getBytes())); 40 | // String decoded = decode(encoded, key); 41 | // System.out.println(decoded); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /simplify/ObfuscatedApp/app/src/main/java/org/cf/obfuscated/MainActivity.java: -------------------------------------------------------------------------------- 1 | package org.cf.obfuscated; 2 | 3 | import android.os.Bundle; 4 | import androidx.appcompat.app.AppCompatActivity; 5 | import android.view.Menu; 6 | import android.view.MenuItem; 7 | 8 | 9 | public class MainActivity extends AppCompatActivity { 10 | 11 | @Override 12 | protected void onCreate(Bundle savedInstanceState) { 13 | super.onCreate(savedInstanceState); 14 | setContentView(R.layout.activity_main); 15 | // for (int i = 0; i < 11; i++) { 16 | // Log.d("StringHolder", i + ": " + StringHolder.get(i)); 17 | // } 18 | 19 | try { 20 | } catch (Exception e) { 21 | e.printStackTrace(); 22 | } 23 | } 24 | 25 | 26 | @Override 27 | public boolean onCreateOptionsMenu(Menu menu) { 28 | // Inflate the menu; this adds items to the action bar if it is present. 29 | getMenuInflater().inflate(R.menu.main, menu); 30 | return true; 31 | } 32 | 33 | @Override 34 | public boolean onOptionsItemSelected(MenuItem item) { 35 | // Handle action bar item clicks here. The action bar will 36 | // automatically handle clicks on the Home/Up button, so long 37 | // as you specify a parent activity in AndroidManifest.xml. 38 | int id = item.getItemId(); 39 | if (id == R.id.action_settings) { 40 | return true; 41 | } 42 | return super.onOptionsItemSelected(item); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /simplify/ObfuscatedApp/app/src/main/java/org/cf/obfuscated/MathCrypt.java: -------------------------------------------------------------------------------- 1 | package org.cf.obfuscated; 2 | 3 | import java.util.LinkedList; 4 | import java.util.List; 5 | import java.util.Random; 6 | 7 | public class MathCrypt { 8 | 9 | private static int sieveCount = 1000; 10 | private static int[] primes = getPrimes(); 11 | 12 | private static int[] getPrimes() { 13 | // Ooh, thank you CS degree! 14 | int stop = (int) Math.sqrt(sieveCount); 15 | boolean[] isComposite = new boolean[sieveCount + 1]; 16 | for (int m = 2; m <= stop; m++) { 17 | if (!isComposite[m]) { 18 | // Every multiple of m is composite 19 | for (int k = m * m; k <= sieveCount; k += m) { 20 | isComposite[k] = true; 21 | } 22 | } 23 | } 24 | 25 | List primeList = new LinkedList(); 26 | for (int m = 0; m <= sieveCount; m++) { 27 | if (!isComposite[m]) { 28 | primeList.add(m); 29 | } 30 | } 31 | 32 | int[] primes = new int[primeList.size()]; 33 | int index = 0; 34 | for ( Integer prime : primeList ) { 35 | primes[index++] = prime; 36 | } 37 | 38 | return primes; 39 | } 40 | 41 | public static int decode(int[] xyz) { 42 | return decode(xyz[0], xyz[1], xyz[2]); 43 | } 44 | 45 | public static int decode(int x, int y, int z) { 46 | int result = primes[x]; 47 | result *= primes[y]; 48 | result <<= 2; 49 | result -= z; 50 | 51 | return result; 52 | } 53 | 54 | public static int[] encode(int num) { 55 | // Pulled directly from ass. Do not actually ever use this. 56 | int[] encoded = new int[3]; 57 | 58 | Random rnd = new Random(); 59 | encoded[0] = rnd.nextInt(primes.length); 60 | encoded[1] = rnd.nextInt(primes.length); 61 | 62 | int wankershim = primes[encoded[0]] * primes[encoded[1]]; 63 | wankershim <<= 2; 64 | encoded[2] = wankershim - num; 65 | 66 | return encoded; 67 | } 68 | 69 | public static void main(String[] argv) { 70 | // int[] encoded = encode(42); 71 | // System.out.println(Arrays.toString(encoded)); 72 | // System.out.println("" + decode(encoded)); 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /simplify/ObfuscatedApp/app/src/main/java/org/cf/obfuscated/Reflection.java: -------------------------------------------------------------------------------- 1 | package org.cf.obfuscated; 2 | 3 | 4 | import java.lang.reflect.Field; 5 | import java.lang.reflect.Method; 6 | 7 | public class Reflection { 8 | 9 | private static String someField = "this is some field, eh?"; 10 | 11 | private static void reflectSecretMethod() { 12 | try { 13 | Class klazz = Class.forName(StringHolder.get(9)); 14 | Method m = klazz.getDeclaredMethod( 15 | StringHolder.get(7) 16 | , Class.forName(StringHolder.get(8)) 17 | , Class.forName(StringHolder.get(8)) 18 | , Class.forName(StringHolder.get(8)) 19 | ); 20 | // Expected: 42 21 | Integer magic = (Integer) m.invoke(null, 36, 30, 64922); 22 | System.out.println("magic answer = " + magic); 23 | } catch (Exception e) { 24 | e.printStackTrace(); 25 | } 26 | } 27 | 28 | private static void reflectSecretMethod2() { 29 | try { 30 | Class klazz = Class.forName(StringHolder.get(9)); 31 | Method m = klazz.getDeclaredMethod(StringHolder.get(10)); 32 | m.invoke(null); 33 | } catch (Exception e) { 34 | e.printStackTrace(); 35 | } 36 | } 37 | 38 | private static int secretMethod(Integer x, Integer y, Integer z) { 39 | return MathCrypt.decode(x, y, z); 40 | } 41 | 42 | private static void secretMethod2() { 43 | System.gc(); 44 | } 45 | 46 | private static void reflectedFieldLookup() throws Exception { 47 | String fieldName = new String(new byte[] {115,111,109,101,70,105,101,108,100}); // "someField" 48 | Field f = Reflection.class.getDeclaredField(fieldName); 49 | String xorKey = (String) f.get(null); 50 | System.out.println(xorKey); 51 | } 52 | 53 | public static void main(String[] argv) throws Exception { 54 | // System.out.println("7 = " + StringHolder.get(7)); 55 | // System.out.println("8 = " + StringHolder.get(8)); 56 | // System.out.println("9 = " + StringHolder.get(9)); 57 | // reflectSecretMethod(); 58 | // reflectedFieldLookup(); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /simplify/ObfuscatedApp/app/src/main/java/org/cf/obfuscated/WhiteNoise.java: -------------------------------------------------------------------------------- 1 | package org.cf.obfuscated; 2 | 3 | public class WhiteNoise { 4 | 5 | private static final int five = 5; 6 | private static final int ten = 10; 7 | 8 | public static void messyMethod() { 9 | Integer i; 10 | i = new Integer(12345); 11 | i = Integer.parseInt(new String(new char[] {'1', '0'})); 12 | i *= Integer.valueOf(3); 13 | i += Integer.valueOf(24); 14 | i /= Integer.valueOf(3); 15 | i -= Integer.valueOf(8); 16 | realTarget(); 17 | i = Integer.parseInt(new String(new char[] {'3', '9'})); 18 | byte[] noise = new byte[i]; 19 | i = Integer.parseInt(new String(new char[] {'2', '4'})); 20 | i *= Integer.valueOf(4); 21 | i += Integer.valueOf(12); 22 | i /= Integer.valueOf(2); 23 | i -= Integer.valueOf(6); 24 | } 25 | 26 | public static int convolutedMethod() { 27 | return stepA1() * stepB1(); 28 | } 29 | 30 | private static void realTarget() { 31 | System.gc(); 32 | } 33 | 34 | private static int stepA1() { 35 | return stepA2(); 36 | } 37 | 38 | private static int stepA2() { 39 | return ten; 40 | } 41 | 42 | private static int stepB1() { 43 | return stepB2(); 44 | } 45 | 46 | private static int stepB2() { 47 | return five; 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /simplify/ObfuscatedApp/app/src/main/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CalebFenton/simplify/29fb25d624aecf0b075dea5c6029b2541474ddfe/simplify/ObfuscatedApp/app/src/main/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /simplify/ObfuscatedApp/app/src/main/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CalebFenton/simplify/29fb25d624aecf0b075dea5c6029b2541474ddfe/simplify/ObfuscatedApp/app/src/main/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /simplify/ObfuscatedApp/app/src/main/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CalebFenton/simplify/29fb25d624aecf0b075dea5c6029b2541474ddfe/simplify/ObfuscatedApp/app/src/main/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /simplify/ObfuscatedApp/app/src/main/res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CalebFenton/simplify/29fb25d624aecf0b075dea5c6029b2541474ddfe/simplify/ObfuscatedApp/app/src/main/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /simplify/ObfuscatedApp/app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 10 | 11 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /simplify/ObfuscatedApp/app/src/main/res/menu/main.xml: -------------------------------------------------------------------------------- 1 | 5 | 9 | 10 | -------------------------------------------------------------------------------- /simplify/ObfuscatedApp/app/src/main/res/values-v21/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /simplify/ObfuscatedApp/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'idea' 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | google() 7 | maven { 8 | url 'https://maven.google.com/' 9 | name 'Google' 10 | } 11 | } 12 | dependencies { 13 | classpath 'com.android.tools.build:gradle:4.0.1' 14 | 15 | // NOTE: Do not place your application dependencies here; they belong 16 | // in the individual module build.gradle files 17 | } 18 | } 19 | 20 | allprojects { 21 | repositories { 22 | jcenter() 23 | maven { 24 | url 'https://maven.google.com/' 25 | name 'Google' 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /simplify/ObfuscatedApp/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Settings specified in this file will override any Gradle settings 5 | # configured through the IDE. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true 19 | android.enableJetifier=true 20 | android.useAndroidX=true 21 | org.gradle.jvmargs=-Xmx1536M 22 | -------------------------------------------------------------------------------- /simplify/ObfuscatedApp/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CalebFenton/simplify/29fb25d624aecf0b075dea5c6029b2541474ddfe/simplify/ObfuscatedApp/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /simplify/ObfuscatedApp/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 12 15:30:13 PDT 2020 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip 7 | -------------------------------------------------------------------------------- /simplify/ObfuscatedApp/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | -------------------------------------------------------------------------------- /simplify/obfuscated-app.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CalebFenton/simplify/29fb25d624aecf0b075dea5c6029b2541474ddfe/simplify/obfuscated-app.apk -------------------------------------------------------------------------------- /simplify/src/main/java/org/cf/simplify/Dependency.java: -------------------------------------------------------------------------------- 1 | package org.cf.simplify; 2 | 3 | /* 4 | * Dependency interface we can mock to get away from statics 5 | */ 6 | public interface Dependency { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /simplify/src/main/java/org/cf/simplify/Main.java: -------------------------------------------------------------------------------- 1 | package org.cf.simplify; 2 | 3 | import org.cf.smalivm.VirtualMachineFactory; 4 | 5 | import java.io.IOException; 6 | 7 | public class Main { 8 | 9 | private static Launcher launcher; 10 | 11 | public static void main(String[] args) throws IOException { 12 | setupLauncher(); 13 | launcher.run(args); 14 | } 15 | 16 | static void setLauncher(Launcher launcher) { 17 | Main.launcher = launcher; 18 | } 19 | 20 | private static void setupLauncher() { 21 | if (launcher == null) { 22 | VirtualMachineFactory vmFactory = new VirtualMachineFactory(); 23 | launcher = new Launcher(vmFactory); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /simplify/src/main/java/org/cf/simplify/strategy/OptimizationStrategy.java: -------------------------------------------------------------------------------- 1 | package org.cf.simplify.strategy; 2 | 3 | import java.util.Map; 4 | 5 | public interface OptimizationStrategy { 6 | 7 | Map getOptimizationCounts(); 8 | 9 | boolean perform(); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /simplify/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | %d{HH:mm:ss.SSS} %-5level %-12logger{12} - %msg%n 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /simplify/src/test/java/org/cf/simplify/LauncherTest.java: -------------------------------------------------------------------------------- 1 | package org.cf.simplify; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertTrue; 4 | 5 | import java.io.File; 6 | import java.io.IOException; 7 | import java.nio.file.Files; 8 | import org.cf.smalivm.VirtualMachineFactory; 9 | import org.cf.smalivm.exception.UnhandledVirtualException; 10 | import org.junit.jupiter.api.Test; 11 | 12 | public class LauncherTest { 13 | 14 | @Test 15 | public void runsWithoutMajorFailureWithSmaliFolder() throws IOException, UnhandledVirtualException { 16 | Launcher launcher = new Launcher(new VirtualMachineFactory()); 17 | File outFile = File.createTempFile("simplify-test", ".tmp"); 18 | launcher.run(new String[] { "src/test/resources/obfuscated-example", "-it", "WhiteNoise", "-o", outFile.getAbsolutePath() }); 19 | 20 | assertTrue(outFile.exists()); 21 | Files.delete(outFile.toPath()); 22 | } 23 | 24 | @Test 25 | public void runsWithoutMajorFailureWithDexFile() throws IOException, UnhandledVirtualException { 26 | Launcher launcher = new Launcher(new VirtualMachineFactory()); 27 | File outFile = File.createTempFile("simplify-test", ".tmp"); 28 | launcher.run(new String[] { "src/test/resources/obfuscated-example.zip", "-it", "WhiteNoise", "-o", 29 | outFile.getAbsolutePath() }); 30 | 31 | assertTrue(outFile.exists()); 32 | Files.delete(outFile.toPath()); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /simplify/src/test/java/org/cf/simplify/MainTest.java: -------------------------------------------------------------------------------- 1 | package org.cf.simplify; 2 | 3 | import static org.mockito.ArgumentMatchers.eq; 4 | import static org.mockito.Mockito.mock; 5 | import static org.mockito.Mockito.times; 6 | import static org.mockito.Mockito.verify; 7 | 8 | import java.io.IOException; 9 | import org.cf.smalivm.exception.UnhandledVirtualException; 10 | import org.junit.jupiter.api.Test; 11 | 12 | public class MainTest { 13 | 14 | @Test 15 | public void runsLauncher() throws IOException, UnhandledVirtualException { 16 | Launcher launcher = mock(Launcher.class); 17 | Main.setLauncher(launcher); 18 | String[] args = new String[0]; 19 | Main.main(args); 20 | 21 | verify(launcher, times(1)).run(eq(args)); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /simplify/src/test/java/org/cf/simplify/OptimizerTester.java: -------------------------------------------------------------------------------- 1 | package org.cf.simplify; 2 | 3 | import org.cf.smalivm.VMState; 4 | import org.cf.smalivm.VMTester; 5 | import org.cf.smalivm.VirtualMachine; 6 | import org.cf.smalivm.context.ExecutionGraph; 7 | import org.cf.smalivm.type.VirtualMethod; 8 | import org.jf.dexlib2.writer.builder.DexBuilder; 9 | 10 | public class OptimizerTester { 11 | 12 | public static ExecutionGraphManipulator getGraphManipulator(String className, String methodSignature, Object... args) { 13 | VMState initial = new VMState(); 14 | if (args.length > 0) { 15 | initial.setRegisters(args); 16 | } 17 | 18 | return getGraphManipulator(className, methodSignature, initial); 19 | } 20 | 21 | public static ExecutionGraphManipulator getGraphManipulator(String className, String methodDescriptor, VMState initial) { 22 | // Force reloading of classes since implementations in class definitions may have changed 23 | VirtualMachine vm = VMTester.spawnVM(true); 24 | 25 | return getGraphManipulator(vm, className, methodDescriptor, initial); 26 | } 27 | 28 | public static ExecutionGraphManipulator getGraphManipulator(VirtualMachine vm, String className, 29 | String methodDescriptor, VMState initial) { 30 | ExecutionGraph graph = VMTester.execute(vm, className, methodDescriptor, initial); 31 | 32 | String methodSignature = className + "->" + methodDescriptor; 33 | VirtualMethod method = vm.getClassManager().getMethod(methodSignature); 34 | DexBuilder dexBuilder = VMTester.getDexBuilder(); 35 | 36 | return new ExecutionGraphManipulator(graph, method, vm, dexBuilder); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /simplify/src/test/resources/logback-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | %d{HH:mm:ss.SSS} %level %logger - %msg%n 5 | 6 | 7 | 8 | 9 | 10 | %d{HH:mm:ss.SSS} %-5level %-12logger{12} - %msg%n 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /simplify/src/test/resources/obfuscated-example.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CalebFenton/simplify/29fb25d624aecf0b075dea5c6029b2541474ddfe/simplify/src/test/resources/obfuscated-example.zip -------------------------------------------------------------------------------- /simplify/src/test/resources/obfuscated-example/org/cf/obfuscated/BuildConfig.smali: -------------------------------------------------------------------------------- 1 | .class public final Lorg/cf/obfuscated/BuildConfig; 2 | .super Ljava/lang/Object; 3 | .source "BuildConfig.java" 4 | 5 | 6 | # static fields 7 | .field public static final APPLICATION_ID:Ljava/lang/String; = "org.cf.obfuscated" 8 | 9 | .field public static final BUILD_TYPE:Ljava/lang/String; = "release" 10 | 11 | .field public static final DEBUG:Z = false 12 | 13 | .field public static final FLAVOR:Ljava/lang/String; = "" 14 | 15 | .field public static final VERSION_CODE:I = 0x1 16 | 17 | .field public static final VERSION_NAME:Ljava/lang/String; = "1.0" 18 | 19 | 20 | # direct methods 21 | .method public constructor ()V 22 | .locals 0 23 | 24 | #@0 25 | .prologue 26 | .line 6 27 | invoke-direct {p0}, Ljava/lang/Object;->()V 28 | 29 | #@3 30 | return-void 31 | .end method 32 | -------------------------------------------------------------------------------- /simplify/src/test/resources/obfuscated-example/org/cf/obfuscated/R$anim.smali: -------------------------------------------------------------------------------- 1 | .class public final Lorg/cf/obfuscated/R$anim; 2 | .super Ljava/lang/Object; 3 | .source "R.java" 4 | 5 | 6 | # annotations 7 | .annotation system Ldalvik/annotation/EnclosingClass; 8 | value = Lorg/cf/obfuscated/R; 9 | .end annotation 10 | 11 | .annotation system Ldalvik/annotation/InnerClass; 12 | accessFlags = 0x19 13 | name = "anim" 14 | .end annotation 15 | 16 | 17 | # static fields 18 | .field public static final abc_fade_in:I = 0x7f040000 19 | 20 | .field public static final abc_fade_out:I = 0x7f040001 21 | 22 | .field public static final abc_slide_in_bottom:I = 0x7f040002 23 | 24 | .field public static final abc_slide_in_top:I = 0x7f040003 25 | 26 | .field public static final abc_slide_out_bottom:I = 0x7f040004 27 | 28 | .field public static final abc_slide_out_top:I = 0x7f040005 29 | 30 | 31 | # direct methods 32 | .method public constructor ()V 33 | .locals 0 34 | 35 | #@0 36 | .prologue 37 | .line 11 38 | invoke-direct {p0}, Ljava/lang/Object;->()V 39 | 40 | #@3 41 | return-void 42 | .end method 43 | -------------------------------------------------------------------------------- /simplify/src/test/resources/obfuscated-example/org/cf/obfuscated/R$bool.smali: -------------------------------------------------------------------------------- 1 | .class public final Lorg/cf/obfuscated/R$bool; 2 | .super Ljava/lang/Object; 3 | .source "R.java" 4 | 5 | 6 | # annotations 7 | .annotation system Ldalvik/annotation/EnclosingClass; 8 | value = Lorg/cf/obfuscated/R; 9 | .end annotation 10 | 11 | .annotation system Ldalvik/annotation/InnerClass; 12 | accessFlags = 0x19 13 | name = "bool" 14 | .end annotation 15 | 16 | 17 | # static fields 18 | .field public static final abc_action_bar_embed_tabs:I = 0x7f050000 19 | 20 | .field public static final abc_action_bar_embed_tabs_pre_jb:I = 0x7f050001 21 | 22 | .field public static final abc_action_bar_expanded_action_views_exclusive:I = 0x7f050002 23 | 24 | .field public static final abc_config_actionMenuItemAllCaps:I = 0x7f050003 25 | 26 | .field public static final abc_config_allowActionMenuItemTextWithIcon:I = 0x7f050004 27 | 28 | .field public static final abc_config_showMenuShortcutsWhenKeyboardPresent:I = 0x7f050005 29 | 30 | 31 | # direct methods 32 | .method public constructor ()V 33 | .locals 0 34 | 35 | #@0 36 | .prologue 37 | .line 1135 38 | invoke-direct {p0}, Ljava/lang/Object;->()V 39 | 40 | #@3 41 | return-void 42 | .end method 43 | -------------------------------------------------------------------------------- /simplify/src/test/resources/obfuscated-example/org/cf/obfuscated/R$integer.smali: -------------------------------------------------------------------------------- 1 | .class public final Lorg/cf/obfuscated/R$integer; 2 | .super Ljava/lang/Object; 3 | .source "R.java" 4 | 5 | 6 | # annotations 7 | .annotation system Ldalvik/annotation/EnclosingClass; 8 | value = Lorg/cf/obfuscated/R; 9 | .end annotation 10 | 11 | .annotation system Ldalvik/annotation/InnerClass; 12 | accessFlags = 0x19 13 | name = "integer" 14 | .end annotation 15 | 16 | 17 | # static fields 18 | .field public static final abc_max_action_buttons:I = 0x7f090000 19 | 20 | 21 | # direct methods 22 | .method public constructor ()V 23 | .locals 0 24 | 25 | #@0 26 | .prologue 27 | .line 1370 28 | invoke-direct {p0}, Ljava/lang/Object;->()V 29 | 30 | #@3 31 | return-void 32 | .end method 33 | -------------------------------------------------------------------------------- /simplify/src/test/resources/obfuscated-example/org/cf/obfuscated/R$menu.smali: -------------------------------------------------------------------------------- 1 | .class public final Lorg/cf/obfuscated/R$menu; 2 | .super Ljava/lang/Object; 3 | .source "R.java" 4 | 5 | 6 | # annotations 7 | .annotation system Ldalvik/annotation/EnclosingClass; 8 | value = Lorg/cf/obfuscated/R; 9 | .end annotation 10 | 11 | .annotation system Ldalvik/annotation/InnerClass; 12 | accessFlags = 0x19 13 | name = "menu" 14 | .end annotation 15 | 16 | 17 | # static fields 18 | .field public static final main:I = 0x7f0c0000 19 | 20 | 21 | # direct methods 22 | .method public constructor ()V 23 | .locals 0 24 | 25 | #@0 26 | .prologue 27 | .line 1400 28 | invoke-direct {p0}, Ljava/lang/Object;->()V 29 | 30 | #@3 31 | return-void 32 | .end method 33 | -------------------------------------------------------------------------------- /simplify/src/test/resources/obfuscated-example/org/cf/obfuscated/R.smali: -------------------------------------------------------------------------------- 1 | .class public final Lorg/cf/obfuscated/R; 2 | .super Ljava/lang/Object; 3 | .source "R.java" 4 | 5 | 6 | # annotations 7 | .annotation system Ldalvik/annotation/MemberClasses; 8 | value = { 9 | Lorg/cf/obfuscated/R$styleable;, 10 | Lorg/cf/obfuscated/R$style;, 11 | Lorg/cf/obfuscated/R$string;, 12 | Lorg/cf/obfuscated/R$menu;, 13 | Lorg/cf/obfuscated/R$layout;, 14 | Lorg/cf/obfuscated/R$integer;, 15 | Lorg/cf/obfuscated/R$id;, 16 | Lorg/cf/obfuscated/R$drawable;, 17 | Lorg/cf/obfuscated/R$dimen;, 18 | Lorg/cf/obfuscated/R$color;, 19 | Lorg/cf/obfuscated/R$bool;, 20 | Lorg/cf/obfuscated/R$attr;, 21 | Lorg/cf/obfuscated/R$anim; 22 | } 23 | .end annotation 24 | 25 | 26 | # direct methods 27 | .method public constructor ()V 28 | .locals 0 29 | 30 | #@0 31 | .prologue 32 | .line 10 33 | invoke-direct {p0}, Ljava/lang/Object;->()V 34 | 35 | #@3 36 | .line 1664 37 | return-void 38 | .end method 39 | -------------------------------------------------------------------------------- /simplify/src/test/resources/smali/constant_propigation_strategy_test.smali: -------------------------------------------------------------------------------- 1 | .class Lconstant_propigation_strategy_test; 2 | .super Ljava/lang/Object; 3 | 4 | # TODO: Long, Float, Double, Byte, Char, Class and String 5 | .method public static addInt2Addr()V 6 | .locals 1 7 | 8 | add-int/2addr v0, v0 9 | 10 | return-void 11 | .end method 12 | 13 | .method public static moveV0IntoV1()V 14 | .locals 2 15 | 16 | move v1, v0 17 | 18 | return-void 19 | .end method 20 | 21 | .method public static invokeIntegerMethods()I 22 | .locals 2 23 | 24 | new-instance v0, Ljava/lang/Integer; 25 | const/4 v1, 0x1 26 | invoke-direct {v0, v1}, Ljava/lang/Integer;->(I)V 27 | invoke-virtual {v0}, Ljava/lang/Integer;->intValue()I 28 | move-result v0 29 | 30 | return v0 31 | .end method 32 | 33 | .method public static useAddParameterToZero(I)I 34 | .locals 1 35 | 36 | const/4 v0, 0x0 37 | add-int/2addr v0, p0 38 | 39 | return v0 40 | .end method 41 | 42 | .method public static getStaticIntegerMaxValue()V 43 | .locals 1 44 | 45 | sget v0, Ljava/lang/Integer;->MAX_VALUE:I 46 | 47 | return-void 48 | .end method 49 | 50 | .method public static arrayGetFromV0AtV1ToV0()V 51 | .locals 2 52 | 53 | aget v0, v0, v1 54 | 55 | return-void 56 | .end method 57 | 58 | .method public static nonDeterministicallyStaticGetIntegerMaxValue(I)V 59 | .locals 1 60 | 61 | if-eqz p0, :end 62 | 63 | sget v0, Ljava/lang/Integer;->MAX_VALUE:I 64 | 65 | :end 66 | return-void 67 | .end method 68 | 69 | .method private static addSelfNoSideEffects(I)I 70 | .locals 0 71 | 72 | add-int/2addr p0, p0 73 | 74 | return p0 75 | .end method 76 | 77 | .method private static addSelfWithSideEffects(I)I 78 | .locals 0 79 | 80 | invoke-static {}, Lunknown_class;->unknownMethodHasSideEffects()V 81 | add-int/2addr p0, p0 82 | 83 | return p0 84 | .end method 85 | 86 | .method private static integerValueOf()Ljava/lang/Integer; 87 | .locals 1 88 | 89 | invoke-static {v0}, Ljava/lang/Integer;->valueOf(I)Ljava/lang/Integer; 90 | move-result-object v0 91 | 92 | return-object v0 93 | .end method 94 | -------------------------------------------------------------------------------- /simplify/src/test/resources/smali/peephole_strategy_test.smali: -------------------------------------------------------------------------------- 1 | .class Lpeephole_strategy_test; 2 | .super Ljava/lang/Object; 3 | 4 | .method public static classForName()V 5 | .locals 1 6 | 7 | :try_start_0 8 | invoke-static {v0}, Ljava/lang/Class;->forName(Ljava/lang/String;)Ljava/lang/Class; 9 | move-result v0 10 | :try_end_0 11 | .catch Ljava/lang/Exception; {:try_start_0 .. :try_end_0} :catch_0 12 | 13 | :catch_0 14 | return-void 15 | .end method 16 | 17 | .method public static stringInit()V 18 | .locals 2 19 | 20 | invoke-direct {v0, v1}, Ljava/lang/String;->([B)V 21 | 22 | return-void 23 | .end method 24 | 25 | .method public static constantPredicate()I 26 | .locals 1 27 | 28 | const/4 v0, 0x0 29 | if-eq v0, v0, :end 30 | 31 | const/4 v0, 0x1 32 | 33 | :end 34 | return v0 35 | .end method 36 | 37 | .method public static activeCheckCast(Ljava/lang/Object;)V 38 | .locals 0 39 | 40 | check-cast p0, Ljava/lang/Integer; 41 | return-void 42 | .end method 43 | 44 | .method public static activeCheckCastWithMultiplePaths(Ljava/lang/Object;)V 45 | .locals 1 46 | 47 | if-eqz p0, :check 48 | 49 | const/4 v0, 0x0 50 | invoke-static {v0}, Ljava/lang/Integer;->valueOf(I)Ljava/lang/Integer; 51 | move-result p0 52 | 53 | :check 54 | check-cast p0, Ljava/lang/Integer; 55 | return-void 56 | .end method 57 | 58 | .method public static uselessCheckCast(I)V 59 | .locals 0 60 | 61 | check-cast p0, I 62 | return-void 63 | .end method 64 | 65 | .method public static uselessCheckCastWithMultiplePaths(I)V 66 | .locals 0 67 | 68 | if-eqz p0, :check 69 | 70 | sget p0, Ljava/lang/Integer;->MAX_VALUE:I 71 | 72 | :check 73 | check-cast p0, I 74 | return-void 75 | .end method 76 | 77 | .method public invokeGetClassOnThis()V 78 | .locals 1 79 | 80 | invoke-virtual {p0}, Ljava/lang/Object;->getClass()Ljava/lang/Class; 81 | move-result v0 82 | 83 | return-void 84 | .end method 85 | 86 | .method public invokeRangeGetClassOnThis()V 87 | .locals 1 88 | 89 | invoke-virtual/range {p0 .. p0}, Ljava/lang/Object;->getClass()Ljava/lang/Class; 90 | move-result v0 91 | 92 | return-void 93 | .end method 94 | -------------------------------------------------------------------------------- /smalivm/libs/android-local.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CalebFenton/simplify/29fb25d624aecf0b075dea5c6029b2541474ddfe/smalivm/libs/android-local.jar -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/ExceptionFactory.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm; 2 | 3 | import org.cf.smalivm.opcode.Op; 4 | import org.cf.util.ClassNameUtils; 5 | 6 | import java.lang.reflect.Constructor; 7 | 8 | public class ExceptionFactory { 9 | 10 | private final VirtualMachine vm; 11 | 12 | ExceptionFactory(VirtualMachine vm) { 13 | this.vm = vm; 14 | } 15 | 16 | public Throwable build(Op op, String className) { 17 | return build(op, className, null); 18 | } 19 | 20 | public Throwable build(Op op, Class exceptionClass) { 21 | return build(op, exceptionClass, null); 22 | } 23 | 24 | public Throwable build(Op op, Class exceptionClass, String message) { 25 | try { 26 | Constructor ctor = exceptionClass.getDeclaredConstructor(String.class); 27 | ctor.setAccessible(true); 28 | return ctor.newInstance(message); 29 | } catch (Exception e) { 30 | e.printStackTrace(); 31 | } 32 | 33 | return new Exception(); 34 | } 35 | 36 | public Throwable build(Op op, String className, String message) { 37 | String binaryName = ClassNameUtils.internalToBinary(className); 38 | try { 39 | @SuppressWarnings("unchecked") 40 | Class exceptionClass = (Class) vm.getClassLoader().loadClass(binaryName); 41 | return build(op, exceptionClass, message); 42 | } catch (Exception e) { 43 | e.printStackTrace(); 44 | } 45 | 46 | return new Exception(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/ObjectInstantiator.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm; 2 | 3 | import java.lang.reflect.Constructor; 4 | import java.lang.reflect.InvocationTargetException; 5 | 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import com.google.common.base.Defaults; 10 | 11 | public class ObjectInstantiator { 12 | 13 | private static final Logger log = LoggerFactory.getLogger(ObjectInstantiator.class.getSimpleName()); 14 | 15 | public static Object newInstance(Class klazz) throws InstantiationException, IllegalAccessException, 16 | IllegalArgumentException, InvocationTargetException { 17 | if (Enum.class.isAssignableFrom(klazz)) { 18 | return newEnumInstance(klazz); 19 | } 20 | 21 | Object newInstance; 22 | try { 23 | // Try it without any funny business. 24 | newInstance = klazz.newInstance(); 25 | } catch (InstantiationException | IllegalAccessException e) { 26 | if (log.isTraceEnabled()) { 27 | log.trace("{} has no default constructor, picking another", klazz); 28 | } 29 | 30 | // Alright, we'll try it the hard way. 31 | Constructor[] ctors = klazz.getDeclaredConstructors(); 32 | Constructor ctor = ctors[0]; 33 | ctor.setAccessible(true); // the little games we play, java... 34 | Object[] args = new Object[ctor.getParameterCount()]; 35 | Class[] parameterTypes = ctor.getParameterTypes(); 36 | for (int i = 0; i < args.length; i++) { 37 | Class parameterType = parameterTypes[i]; 38 | args[i] = Defaults.defaultValue(parameterType); 39 | } 40 | newInstance = ctor.newInstance(args); 41 | } 42 | 43 | return newInstance; 44 | } 45 | 46 | @SuppressWarnings({ "unchecked", "rawtypes" }) 47 | private static Object newEnumInstance(Class klazz) { 48 | return Enum.valueOf((Class) klazz, "$shadow_instance"); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/SideEffect.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm; 2 | 3 | public class SideEffect { 4 | 5 | public enum Level { 6 | NONE(0), // reflected, emulated, white listed, or otherwise safe 7 | WEAK(1), // not white listed, unknown 8 | STRONG(2), // member variable modification 9 | ; 10 | 11 | private final int value; 12 | 13 | Level(int value) { 14 | this.value = value; 15 | } 16 | 17 | public int getValue() { 18 | return value; 19 | } 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/TemplateStateFactory.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm; 2 | 3 | import org.cf.smalivm.context.ClassState; 4 | import org.cf.smalivm.context.ExecutionContext; 5 | import org.cf.smalivm.context.HeapItem; 6 | import org.cf.smalivm.context.MethodState; 7 | import org.cf.smalivm.type.UninitializedInstance; 8 | import org.cf.smalivm.type.VirtualField; 9 | import org.cf.smalivm.type.VirtualMethod; 10 | import org.cf.smalivm.type.VirtualType; 11 | import org.cf.util.Utils; 12 | 13 | import java.util.List; 14 | 15 | public class TemplateStateFactory { 16 | 17 | public static MethodState forMethod(ExecutionContext context) { 18 | VirtualMethod method = context.getMethod(); 19 | int registerCount = method.getRegisterCount(); 20 | List parameterTypes = method.getParameterTypeNames(); 21 | int parameterSize = Utils.getRegisterSize(parameterTypes); 22 | MethodState mState = new MethodState(context, registerCount, parameterTypes.size(), parameterSize); 23 | int firstParameter = mState.getParameterStart(); 24 | int parameterRegister = firstParameter; 25 | 26 | for (String type : parameterTypes) { 27 | HeapItem item; 28 | if (parameterRegister == firstParameter && !method.isStatic() && method.getName().equals("")) { 29 | UninitializedInstance instance = new UninitializedInstance(method.getDefiningClass()); 30 | item = new HeapItem(instance, type); 31 | } else { 32 | item = HeapItem.newUnknown(type); 33 | } 34 | mState.assignParameter(parameterRegister, item); 35 | parameterRegister += Utils.getRegisterSize(type); 36 | } 37 | 38 | return mState; 39 | } 40 | 41 | public static ClassState forClass(ExecutionContext context, VirtualType virtualClass) { 42 | ClassState cState = new ClassState(virtualClass, context); 43 | for (VirtualField field : virtualClass.getFields()) { 44 | Object value = field.getInitialValue(); 45 | String type = field.getType(); 46 | cState.pokeField(field, new HeapItem(value, type)); 47 | } 48 | 49 | return cState; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/configuration/ConfigurationLoader.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.configuration; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | import java.util.Iterator; 6 | import java.util.LinkedList; 7 | import java.util.List; 8 | 9 | import com.google.common.base.Charsets; 10 | import com.google.common.io.Resources; 11 | 12 | public class ConfigurationLoader { 13 | 14 | public static List load(String path) { 15 | URL url = Resources.getResource(path); 16 | List lines = new LinkedList<>(); 17 | try { 18 | lines = Resources.readLines(url, Charsets.UTF_8); 19 | } catch (IOException e) { 20 | e.printStackTrace(); 21 | } 22 | removeNonDefinitionLines(lines); 23 | 24 | return lines; 25 | } 26 | 27 | private static void removeNonDefinitionLines(List lines) { 28 | Iterator iter = lines.iterator(); 29 | while (iter.hasNext()) { 30 | String line = iter.next(); 31 | if (line.trim().startsWith("//") || line.trim().isEmpty()) { 32 | iter.remove(); 33 | } 34 | } 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/context/CallStack.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.context; 2 | 3 | import gnu.trove.list.TIntList; 4 | import gnu.trove.list.linked.TIntLinkedList; 5 | 6 | import java.util.LinkedList; 7 | import java.util.List; 8 | 9 | public class CallStack { 10 | 11 | private List methodStack; 12 | private TIntList addressStack; 13 | 14 | CallStack() { 15 | methodStack = new LinkedList<>(); 16 | addressStack = new TIntLinkedList(); 17 | } 18 | 19 | CallStack(String methodDescriptor, int address) { 20 | this(); 21 | push(methodDescriptor, address); 22 | } 23 | 24 | CallStack(CallStack callerStack) { 25 | this.methodStack = new LinkedList<>(callerStack.methodStack); 26 | this.addressStack = new TIntLinkedList(callerStack.addressStack); 27 | } 28 | 29 | void push(String methodDescriptor, int address) { 30 | methodStack.add(methodDescriptor); 31 | addressStack.add(address); 32 | } 33 | 34 | String peekMethodDescriptor() { 35 | return methodStack.get(size() - 1); 36 | } 37 | 38 | int size() { 39 | return methodStack.size(); 40 | } 41 | 42 | void pokeAddress(int address) { 43 | addressStack.set(size() - 1, address); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/context/ExecutionGraphIterator.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.context; 2 | 3 | import java.util.ArrayDeque; 4 | import java.util.Deque; 5 | import java.util.Iterator; 6 | 7 | class ExecutionGraphIterator implements Iterator { 8 | 9 | private final Deque stack; 10 | 11 | ExecutionGraphIterator(ExecutionGraph graph) { 12 | stack = new ArrayDeque<>(); 13 | ExecutionNode rootNode = graph.getRoot(); 14 | 15 | if (rootNode != null) { 16 | stack.push(rootNode); 17 | } 18 | } 19 | 20 | @Override 21 | public boolean hasNext() { 22 | return !stack.isEmpty(); 23 | } 24 | 25 | @Override 26 | public ExecutionNode next() { 27 | ExecutionNode result = stack.poll(); 28 | stack.addAll(result.getChildren()); 29 | 30 | return result; 31 | } 32 | 33 | @Override 34 | public void remove() { 35 | throw new UnsupportedOperationException(); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/context/ExecutionGrapher.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.context; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class ExecutionGrapher { 7 | 8 | private final static String DOT = "[^a-zA-Z\200-\377_0-9\\s\\p{Punct}]"; 9 | 10 | public static String graph(ExecutionGraph graph) { 11 | ExecutionNode node = graph.getRoot(); 12 | StringBuilder sb = new StringBuilder("digraph {\n"); 13 | getGraph(node, graph, sb, new ArrayList<>()); 14 | sb.append("labelloc=\"t\"\n"); 15 | sb.append("label=\"").append(graph.getMethod()).append("\";\n"); 16 | sb.append('}'); 17 | 18 | return sb.toString(); 19 | } 20 | 21 | private static void getGraph(ExecutionNode node, ExecutionGraph graph, StringBuilder sb, 22 | List visitedNodes) { 23 | if (visitedNodes.contains(node)) { 24 | return; 25 | } 26 | visitedNodes.add(node); 27 | 28 | StringBuilder nodeState = getNodeState(node, graph); 29 | for (ExecutionNode child : node.getChildren()) { 30 | sb.append(nodeState).append(" -> ").append(getNodeState(child, graph)).append('\n'); 31 | 32 | getGraph(child, graph, sb, visitedNodes); 33 | } 34 | } 35 | 36 | private static StringBuilder getNodeState(ExecutionNode node, ExecutionGraph graph) { 37 | MethodState state = node.getContext().getMethodState(); 38 | String op = node.toString().replaceAll(DOT, "?").replace("\"", "\\\""); 39 | String stateStr = state.toString().replaceAll(DOT, "?").replace("\"", "\\\"").trim(); 40 | int nodeIndex = graph.getNodeIndex(node); 41 | 42 | StringBuilder sb = new StringBuilder(); 43 | sb.append("\"@").append(node.getAddress()).append('.').append(nodeIndex).append(" :: "); 44 | sb.append(op).append('\n').append(stateStr).append('"'); 45 | 46 | return sb; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/context/InstanceState.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.context; 2 | 3 | public class InstanceState extends BaseState { 4 | 5 | InstanceState(ExecutionContext context) { 6 | super(context); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/context/StackTraceBuilder.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.context; 2 | 3 | import org.cf.smalivm.VirtualMachine; 4 | 5 | public class StackTraceBuilder { 6 | 7 | static StackTraceElement[] buildCallStack(VirtualMachine vm, ExecutionContext context) { 8 | // List callStackList = context.getCallStack(); 9 | 10 | // For each MD in list 11 | // Get filename for class 12 | // Get line number - NEED NODE OR OP 13 | return null; 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/context/StackTraceElement.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.context; 2 | 3 | import org.cf.util.ClassNameUtils; 4 | 5 | public class StackTraceElement { 6 | 7 | private String definingClass; 8 | private String methodName; 9 | private String fileName; 10 | private int lineNumber; 11 | 12 | public StackTraceElement(String methodDescriptor, String fileName, int lineNumber) { 13 | String[] parts = methodDescriptor.split("->"); 14 | definingClass = ClassNameUtils.internalToBinary(parts[0]); 15 | methodName = parts[1].split("\\(")[0]; 16 | this.fileName = fileName; 17 | this.lineNumber = lineNumber; 18 | } 19 | 20 | public String getDeclaringClass() { 21 | return definingClass; 22 | } 23 | 24 | public String getMethodName() { 25 | return methodName; 26 | } 27 | 28 | public String getFileName() { 29 | return fileName; 30 | } 31 | 32 | public int getLineNumber() { 33 | return lineNumber; 34 | } 35 | 36 | @Override 37 | public String toString() { 38 | // E.g. java.lang.Thread.getStackTrace(Thread.java:1589) 39 | StringBuilder sb = new StringBuilder(getDeclaringClass()); 40 | sb.append('.').append(getMethodName()).append('(').append(getFileName()).append(':').append(getLineNumber()) 41 | .append(')'); 42 | 43 | return sb.toString(); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/debug/Breakpoint.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.debug; 2 | 3 | 4 | import org.apache.commons.lang3.builder.EqualsBuilder; 5 | import org.apache.commons.lang3.builder.HashCodeBuilder; 6 | 7 | public class Breakpoint implements Comparable { 8 | 9 | private final String methodSignature; 10 | private final int instructionIndex; 11 | 12 | Breakpoint(String methodSignature, int instructionIndex) { 13 | this.methodSignature = methodSignature; 14 | this.instructionIndex = instructionIndex; 15 | } 16 | 17 | @Override 18 | public int hashCode() { 19 | return new HashCodeBuilder(43, 941) 20 | .append(getMethodSignature()) 21 | .append(getInstructionIndex()) 22 | .hashCode(); 23 | } 24 | 25 | public String getMethodSignature() { 26 | return methodSignature; 27 | } 28 | 29 | public int getInstructionIndex() { 30 | return instructionIndex; 31 | } 32 | 33 | @Override 34 | public boolean equals(Object obj) { 35 | if (obj == null) { 36 | return false; 37 | } 38 | if (obj == this) { 39 | return true; 40 | } 41 | if (obj.getClass() != getClass()) { 42 | return false; 43 | } 44 | Breakpoint rhs = (Breakpoint) obj; 45 | 46 | return new EqualsBuilder() 47 | .append(getMethodSignature(), rhs.getMethodSignature()) 48 | .append(getInstructionIndex(), rhs.getInstructionIndex()) 49 | .isEquals(); 50 | } 51 | 52 | public String toString() { 53 | return getMethodSignature() + " : " + getInstructionIndex(); 54 | } 55 | 56 | @Override 57 | public int compareTo(Breakpoint rhs) { 58 | if (getMethodSignature().equals(rhs.getMethodSignature())) { 59 | return rhs.getInstructionIndex() - getInstructionIndex(); 60 | } 61 | else { 62 | return getMethodSignature().compareTo(rhs.getMethodSignature()); 63 | } 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/dex/CommonTypes.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.dex; 2 | 3 | public class CommonTypes { 4 | 5 | public static final String OBJECT = "Ljava/lang/Object;"; 6 | public static final String STRING = "Ljava/lang/String;"; 7 | public static final String CLASS = "Ljava/lang/Class;"; 8 | 9 | public static final String BOOL = "Z"; 10 | public static final String VOID = "V"; 11 | public static final String FLOAT = "F"; 12 | public static final String DOUBLE = "D"; 13 | public static final String LONG = "J"; 14 | public static final String INTEGER = "I"; 15 | public static final String SHORT = "S"; 16 | public static final String CHARACTER = "C"; 17 | 18 | public static final String DOUBLE_OBJ = "Ljava/lang/Double;"; 19 | public static final String FLOAT_OBJ = "Ljava/lang/Float;"; 20 | public static final String INTEGER_OBJ = "Ljava/lang/Integer;"; 21 | public static final String SHORT_OBJ = "Ljava/lang/Short;"; 22 | public static final String LONG_OBJ = "Ljava/lang/Long;"; 23 | public static final String BYTE_OBJ = "Ljava/lang/Byte;"; 24 | public static final String BOOLEAN_OBJ = "Ljava/lang/Boolean;"; 25 | public static final String CHARACTER_OBJ = "Ljava/lang/Character;"; 26 | 27 | public static final String UNKNOWN = "?"; 28 | 29 | } 30 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/emulate/EmulatedMethod.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.emulate; 2 | 3 | import org.cf.smalivm.SideEffect; 4 | import org.cf.smalivm.SideEffect.Level; 5 | 6 | import java.util.HashSet; 7 | import java.util.Set; 8 | 9 | public abstract class EmulatedMethod { 10 | 11 | protected final Set exceptions; 12 | protected SideEffect.Level level; 13 | 14 | EmulatedMethod() { 15 | exceptions = new HashSet<>(); 16 | level = SideEffect.Level.NONE; 17 | } 18 | 19 | public Level getSideEffectLevel() { 20 | return level; 21 | } 22 | 23 | protected void setSideEffectLevel(Level level) { 24 | this.level = level; 25 | } 26 | 27 | public Set getExceptions() { 28 | return exceptions; 29 | } 30 | 31 | protected void setException(Throwable exception) { 32 | exceptions.add(exception); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/emulate/ExecutionContextMethod.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.emulate; 2 | 3 | import org.cf.smalivm.VirtualMachine; 4 | import org.cf.smalivm.context.ExecutionContext; 5 | import org.cf.smalivm.opcode.Op; 6 | 7 | public abstract class ExecutionContextMethod extends EmulatedMethod { 8 | 9 | protected abstract void execute(VirtualMachine vm, Op op, ExecutionContext context); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/emulate/MethodStateMethod.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.emulate; 2 | 3 | import org.cf.smalivm.VirtualMachine; 4 | import org.cf.smalivm.context.MethodState; 5 | import org.cf.smalivm.opcode.Op; 6 | 7 | public abstract class MethodStateMethod extends EmulatedMethod { 8 | 9 | protected abstract void execute(VirtualMachine vm, Op op, MethodState mState); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/emulate/UnknownValuesMethod.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.emulate; 2 | 3 | public interface UnknownValuesMethod { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/emulate/android_text_TextUtils_isEmpty.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.emulate; 2 | 3 | import org.cf.smalivm.VirtualMachine; 4 | import org.cf.smalivm.context.ExecutionContext; 5 | import org.cf.smalivm.context.MethodState; 6 | import org.cf.smalivm.dex.CommonTypes; 7 | import org.cf.smalivm.opcode.Op; 8 | import org.cf.smalivm.type.VirtualClass; 9 | import org.cf.util.ClassNameUtils; 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | 13 | class android_text_TextUtils_isEmpty extends ExecutionContextMethod { 14 | 15 | @SuppressWarnings("unused") 16 | private static final Logger log = LoggerFactory.getLogger(android_text_TextUtils_isEmpty.class.getSimpleName()); 17 | 18 | private static final String RETURN_TYPE = CommonTypes.BOOL; 19 | 20 | @Override 21 | public void execute(VirtualMachine vm, Op op, ExecutionContext context) { 22 | MethodState mState = context.getMethodState(); 23 | CharSequence charSequence = (CharSequence) mState.peekParameter(0).getValue(); 24 | // https://developer.android.com/reference/android/text/TextUtils#isEmpty(java.lang.CharSequence) 25 | boolean isEmpty = charSequence == null || charSequence.length() == 0; 26 | mState.assignReturnRegister(isEmpty, RETURN_TYPE); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/emulate/java_lang_Object_getClass.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.emulate; 2 | 3 | import org.cf.smalivm.VirtualMachine; 4 | import org.cf.smalivm.context.ExecutionContext; 5 | import org.cf.smalivm.context.MethodState; 6 | import org.cf.smalivm.dex.CommonTypes; 7 | import org.cf.smalivm.opcode.Op; 8 | import org.cf.smalivm.type.VirtualType; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | 12 | class java_lang_Object_getClass extends ExecutionContextMethod implements UnknownValuesMethod { 13 | 14 | @SuppressWarnings("unused") 15 | private static final Logger log = LoggerFactory.getLogger(java_lang_Object_getClass.class.getSimpleName()); 16 | 17 | private static final String RETURN_TYPE = CommonTypes.CLASS; 18 | 19 | @Override 20 | public void execute(VirtualMachine vm, Op op, ExecutionContext context) { 21 | MethodState mState = context.getMethodState(); 22 | String argumentType = mState.peekParameter(0).getType(); 23 | VirtualType virtualType = vm.getClassManager().getVirtualType(argumentType); 24 | try { 25 | Class value = vm.getClassLoader().loadClass(virtualType.getBinaryName()); 26 | mState.assignReturnRegister(value, RETURN_TYPE); 27 | } catch (ClassNotFoundException e) { 28 | throw new RuntimeException("Class not found: " + argumentType, e); 29 | } 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/emulate/org_cf_simplify_Utils_breakpoint.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.emulate; 2 | 3 | import org.cf.smalivm.VirtualMachine; 4 | import org.cf.smalivm.context.MethodState; 5 | import org.cf.smalivm.opcode.Op; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | class org_cf_simplify_Utils_breakpoint extends MethodStateMethod { 10 | 11 | private static final Logger log = LoggerFactory.getLogger(org_cf_simplify_Utils_breakpoint.class.getSimpleName()); 12 | 13 | @Override 14 | protected void execute(VirtualMachine vm, Op op, MethodState mState) { 15 | // To use, add invoke-static {}, Lorg/cf/simplify/Utils;->breakpoint()V, and set a breakpoint here. 16 | log.trace("For a good time, set a breakpoint here!"); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/exception/MaxAddressVisitsExceededException.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.exception; 2 | 3 | import org.cf.smalivm.context.ExecutionNode; 4 | 5 | public class MaxAddressVisitsExceededException extends VirtualMachineException { 6 | 7 | private static final long serialVersionUID = 7115169814850980339L; 8 | 9 | public MaxAddressVisitsExceededException(ExecutionNode node, String methodDescriptor) { 10 | super("Exceeded max address visits @" + node.getAddress() + " " + node + " in " + methodDescriptor); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/exception/MaxCallDepthExceededException.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.exception; 2 | 3 | public class MaxCallDepthExceededException extends VirtualMachineException { 4 | 5 | private static final long serialVersionUID = -9148536615221065528L; 6 | 7 | public MaxCallDepthExceededException(String methodDescriptor) { 8 | super("Exceeded max call depth in " + methodDescriptor); 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/exception/MaxExecutionTimeExceededException.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.exception; 2 | 3 | public class MaxExecutionTimeExceededException extends VirtualMachineException { 4 | 5 | private static final long serialVersionUID = -7500776521505568601L; 6 | 7 | public MaxExecutionTimeExceededException(String methodDescriptor) { 8 | super("Exceeded execution time in " + methodDescriptor); 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/exception/MaxMethodVisitsExceededException.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.exception; 2 | 3 | import org.cf.smalivm.context.ExecutionNode; 4 | 5 | public class MaxMethodVisitsExceededException extends VirtualMachineException { 6 | 7 | private static final long serialVersionUID = 2782400703961403297L; 8 | 9 | public MaxMethodVisitsExceededException(ExecutionNode node, String methodDescriptor) { 10 | this("Exceeded max method visits @" + node.getAddress() + " " + node + " in " + methodDescriptor); 11 | } 12 | 13 | private MaxMethodVisitsExceededException(String message) { 14 | super(message); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/exception/UnhandledVirtualException.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.exception; 2 | 3 | public class UnhandledVirtualException extends VirtualMachineException { 4 | 5 | private static final long serialVersionUID = 7055493085764845808L; 6 | 7 | private final Throwable exception; 8 | 9 | public UnhandledVirtualException(Throwable exception) { 10 | super(exception.getMessage()); 11 | this.exception = exception; 12 | } 13 | 14 | @Override 15 | public String toString() { 16 | return "Unhandled virtual exception: " + exception; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/exception/VirtualMachineException.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.exception; 2 | 3 | public abstract class VirtualMachineException extends Exception { 4 | 5 | private static final long serialVersionUID = 367467528566284839L; 6 | 7 | protected VirtualMachineException(String message) { 8 | super(message); 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/opcode/AGetOpFactory.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.opcode; 2 | 3 | import gnu.trove.map.TIntObjectMap; 4 | 5 | import org.cf.smalivm.VirtualMachine; 6 | import org.cf.util.Utils; 7 | import org.jf.dexlib2.builder.MethodLocation; 8 | import org.jf.dexlib2.iface.instruction.formats.Instruction23x; 9 | 10 | public class AGetOpFactory implements OpFactory { 11 | 12 | @Override 13 | public Op create(MethodLocation location, TIntObjectMap addressToLocation, VirtualMachine vm) { 14 | MethodLocation child = Utils.getNextLocation(location, addressToLocation); 15 | Instruction23x instr = (Instruction23x) location.getInstruction(); 16 | int valueRegister = instr.getRegisterA(); 17 | int arrayRegister = instr.getRegisterB(); 18 | int indexRegister = instr.getRegisterC(); 19 | 20 | return new AGetOp(location, child, valueRegister, arrayRegister, indexRegister, vm.getExceptionFactory()); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/opcode/APutOpFactory.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.opcode; 2 | 3 | import gnu.trove.map.TIntObjectMap; 4 | 5 | import org.cf.smalivm.VirtualMachine; 6 | import org.cf.util.Utils; 7 | import org.jf.dexlib2.builder.MethodLocation; 8 | import org.jf.dexlib2.iface.instruction.formats.Instruction23x; 9 | 10 | public class APutOpFactory implements OpFactory { 11 | 12 | @Override 13 | public Op create(MethodLocation location, TIntObjectMap addressToLocation, VirtualMachine vm) { 14 | MethodLocation child = Utils.getNextLocation(location, addressToLocation); 15 | Instruction23x instr = (Instruction23x) location.getInstruction(); 16 | int putRegister = instr.getRegisterA(); 17 | int arrayRegister = instr.getRegisterB(); 18 | int indexRegister = instr.getRegisterC(); 19 | 20 | return new APutOp(location, child, putRegister, arrayRegister, indexRegister, vm.getClassManager(), 21 | vm.getExceptionFactory()); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/opcode/ArrayLengthOpFactory.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.opcode; 2 | 3 | import gnu.trove.map.TIntObjectMap; 4 | 5 | import org.cf.smalivm.VirtualMachine; 6 | import org.cf.util.Utils; 7 | import org.jf.dexlib2.builder.MethodLocation; 8 | import org.jf.dexlib2.iface.instruction.formats.Instruction12x; 9 | 10 | public class ArrayLengthOpFactory implements OpFactory { 11 | 12 | @Override 13 | public Op create(MethodLocation location, TIntObjectMap addressToLocation, VirtualMachine vm) { 14 | MethodLocation child = Utils.getNextLocation(location, addressToLocation); 15 | Instruction12x instr = (Instruction12x) location.getInstruction(); 16 | int destRegister = instr.getRegisterA(); 17 | int arrayRegister = instr.getRegisterB(); 18 | 19 | return new ArrayLengthOp(location, child, destRegister, arrayRegister, vm.getExceptionFactory()); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/opcode/CheckCastOpFactory.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.opcode; 2 | 3 | import gnu.trove.map.TIntObjectMap; 4 | 5 | import org.cf.smalivm.VirtualMachine; 6 | import org.cf.smalivm.type.VirtualType; 7 | import org.cf.util.Utils; 8 | import org.jf.dexlib2.builder.MethodLocation; 9 | import org.jf.dexlib2.iface.instruction.formats.Instruction21c; 10 | import org.jf.dexlib2.iface.reference.TypeReference; 11 | 12 | public class CheckCastOpFactory implements OpFactory { 13 | 14 | @Override 15 | public Op create(MethodLocation location, TIntObjectMap addressToLocation, VirtualMachine vm) { 16 | MethodLocation child = Utils.getNextLocation(location, addressToLocation); 17 | Instruction21c instr = (Instruction21c) location.getInstruction(); 18 | int targetRegister = instr.getRegisterA(); 19 | TypeReference reference = (TypeReference) instr.getReference(); 20 | VirtualType referenceType = vm.getClassManager().getVirtualType(reference); 21 | 22 | return new CheckCastOp(location, child, targetRegister, referenceType, vm.getClassManager(), vm.getExceptionFactory()); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/opcode/CmpOpFactory.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.opcode; 2 | 3 | import gnu.trove.map.TIntObjectMap; 4 | 5 | import org.cf.smalivm.VirtualMachine; 6 | import org.cf.util.Utils; 7 | import org.jf.dexlib2.builder.MethodLocation; 8 | import org.jf.dexlib2.iface.instruction.formats.Instruction23x; 9 | 10 | public class CmpOpFactory implements OpFactory { 11 | 12 | @Override 13 | public Op create(MethodLocation location, TIntObjectMap addressToLocation, VirtualMachine vm) { 14 | MethodLocation child = Utils.getNextLocation(location, addressToLocation); 15 | Instruction23x instr = (Instruction23x) location.getInstruction(); 16 | int destRegister = instr.getRegisterA(); 17 | int lhsRegister = instr.getRegisterB(); 18 | int rhsRegister = instr.getRegisterC(); 19 | 20 | return new CmpOp(location, child, destRegister, lhsRegister, rhsRegister); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/opcode/ExecutionContextOp.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.opcode; 2 | 3 | import org.cf.smalivm.context.ExecutionContext; 4 | import org.cf.smalivm.context.ExecutionNode; 5 | import org.jf.dexlib2.builder.MethodLocation; 6 | 7 | public abstract class ExecutionContextOp extends Op { 8 | 9 | ExecutionContextOp(MethodLocation location, MethodLocation child) { 10 | super(location, child); 11 | } 12 | 13 | ExecutionContextOp(MethodLocation location, MethodLocation[] children) { 14 | super(location, children); 15 | } 16 | 17 | public abstract void execute(ExecutionNode executionNode, ExecutionContext context); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/opcode/FillArrayDataOp.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.opcode; 2 | 3 | import org.cf.smalivm.context.ExecutionNode; 4 | import org.cf.smalivm.context.HeapItem; 5 | import org.cf.smalivm.context.MethodState; 6 | import org.jf.dexlib2.builder.MethodLocation; 7 | 8 | public class FillArrayDataOp extends MethodStateOp { 9 | 10 | private final int register; 11 | private final MethodLocation returnLocation; 12 | 13 | FillArrayDataOp(MethodLocation location, MethodLocation child, MethodLocation returnLocation, int register) { 14 | super(location, child); 15 | 16 | this.returnLocation = returnLocation; 17 | this.register = register; 18 | } 19 | 20 | @Override 21 | public void execute(ExecutionNode node, MethodState mState) { 22 | HeapItem item = mState.readRegister(register); 23 | 24 | // Mark register as assigned because next op will be payload, and it uses assigned register in this op to 25 | // determine target register for payload. 26 | mState.assignRegister(register, item); 27 | 28 | // It needs to know return address when finished since payload ops do not continue to next address. 29 | mState.setPseudoInstructionReturnLocation(returnLocation); 30 | } 31 | 32 | @Override 33 | public String toString() { 34 | return getName() + " r" + register + ", :addr_" + getChildren()[0].getCodeAddress(); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/opcode/FillArrayDataOpFactory.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.opcode; 2 | 3 | import gnu.trove.map.TIntObjectMap; 4 | 5 | import org.cf.smalivm.VirtualMachine; 6 | import org.jf.dexlib2.builder.BuilderInstruction; 7 | import org.jf.dexlib2.builder.MethodLocation; 8 | import org.jf.dexlib2.iface.instruction.OffsetInstruction; 9 | import org.jf.dexlib2.iface.instruction.formats.Instruction31t; 10 | 11 | public class FillArrayDataOpFactory implements OpFactory { 12 | 13 | @Override 14 | public Op create(MethodLocation location, TIntObjectMap addressToLocation, VirtualMachine vm) { 15 | BuilderInstruction instruction = (BuilderInstruction) location.getInstruction(); 16 | int address = instruction.getLocation().getCodeAddress(); 17 | int returnAddress = address + instruction.getCodeUnits(); 18 | MethodLocation returnLocation = addressToLocation.get(returnAddress); 19 | int branchOffset = ((OffsetInstruction) instruction).getCodeOffset(); 20 | int childAddress = address + branchOffset; 21 | MethodLocation child = addressToLocation.get(childAddress); 22 | Instruction31t instr = (Instruction31t) location.getInstruction(); 23 | int register = instr.getRegisterA(); 24 | 25 | return new FillArrayDataOp(location, child, returnLocation, register); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/opcode/FillArrayDataPayloadOpFactory.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.opcode; 2 | 3 | import gnu.trove.map.TIntObjectMap; 4 | 5 | import java.util.List; 6 | 7 | import org.cf.smalivm.VirtualMachine; 8 | import org.jf.dexlib2.builder.MethodLocation; 9 | import org.jf.dexlib2.iface.instruction.formats.ArrayPayload; 10 | 11 | public class FillArrayDataPayloadOpFactory implements OpFactory { 12 | 13 | @Override 14 | public Op create(MethodLocation location, TIntObjectMap addressToLocation, VirtualMachine vm) { 15 | ArrayPayload instr = (ArrayPayload) location.getInstruction(); 16 | int elementWidth = instr.getElementWidth(); 17 | List arrayElements = instr.getArrayElements(); 18 | 19 | return new FillArrayDataPayloadOp(location, elementWidth, arrayElements); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/opcode/GotoOp.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.opcode; 2 | 3 | import org.cf.smalivm.context.ExecutionNode; 4 | import org.cf.smalivm.context.MethodState; 5 | import org.jf.dexlib2.builder.MethodLocation; 6 | 7 | public class GotoOp extends MethodStateOp { 8 | 9 | GotoOp(MethodLocation location, MethodLocation childInstruction) { 10 | super(location, childInstruction); 11 | } 12 | 13 | @Override 14 | public void execute(ExecutionNode node, MethodState mState) { 15 | // https://xkcd.com/292/ 16 | } 17 | 18 | @Override 19 | public String toString() { 20 | StringBuilder sb = new StringBuilder(getName()); 21 | int childAddress = getChildren()[0].getCodeAddress(); 22 | sb.append(" :addr_").append(childAddress); 23 | 24 | return sb.toString(); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/opcode/GotoOpFactory.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.opcode; 2 | 3 | import gnu.trove.map.TIntObjectMap; 4 | 5 | import org.cf.smalivm.VirtualMachine; 6 | import org.jf.dexlib2.builder.BuilderInstruction; 7 | import org.jf.dexlib2.builder.BuilderOffsetInstruction; 8 | import org.jf.dexlib2.builder.Label; 9 | import org.jf.dexlib2.builder.MethodLocation; 10 | 11 | public class GotoOpFactory implements OpFactory { 12 | 13 | @Override 14 | public Op create(MethodLocation location, TIntObjectMap addressToLocation, VirtualMachine vm) { 15 | BuilderInstruction instruction = (BuilderInstruction) location.getInstruction(); 16 | Label target = ((BuilderOffsetInstruction) instruction).getTarget(); 17 | int targetAddress = target.getCodeAddress(); 18 | MethodLocation child = addressToLocation.get(targetAddress); 19 | 20 | return new GotoOp(location, child); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/opcode/IGetOp.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.opcode; 2 | 3 | import org.cf.smalivm.VirtualMachine; 4 | import org.cf.smalivm.context.ExecutionContext; 5 | import org.cf.smalivm.context.ExecutionNode; 6 | import org.cf.smalivm.context.HeapItem; 7 | import org.cf.smalivm.context.MethodState; 8 | import org.jf.dexlib2.builder.MethodLocation; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | 12 | public class IGetOp extends ExecutionContextOp { 13 | 14 | @SuppressWarnings("unused") 15 | private static final Logger log = LoggerFactory.getLogger(IGetOp.class.getSimpleName()); 16 | 17 | private final int destRegister; 18 | private final int instanceRegister; 19 | private final String fieldDescriptor; 20 | private final VirtualMachine vm; 21 | 22 | public IGetOp(MethodLocation location, MethodLocation child, int destRegister, int instanceRegister, 23 | String fieldDescriptor, VirtualMachine vm) { 24 | super(location, child); 25 | 26 | this.destRegister = destRegister; 27 | this.instanceRegister = instanceRegister; 28 | this.fieldDescriptor = fieldDescriptor; 29 | this.vm = vm; 30 | } 31 | 32 | @Override 33 | public void execute(ExecutionNode node, ExecutionContext context) { 34 | // TODO: https://github.com/CalebFenton/simplify/issues/22 35 | MethodState mState = context.getMethodState(); 36 | HeapItem instanceItem = mState.readRegister(instanceRegister); 37 | 38 | String type = fieldDescriptor.split(":")[1]; 39 | mState.assignRegister(destRegister, HeapItem.newUnknown(type)); 40 | } 41 | 42 | @Override 43 | public String toString() { 44 | return getName() + " r" + destRegister + ", r" + instanceRegister + ", " + fieldDescriptor; 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/opcode/IGetOpFactory.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.opcode; 2 | 3 | import gnu.trove.map.TIntObjectMap; 4 | 5 | import org.cf.smalivm.VirtualMachine; 6 | import org.cf.util.Utils; 7 | import org.jf.dexlib2.builder.MethodLocation; 8 | import org.jf.dexlib2.iface.instruction.formats.Instruction22c; 9 | import org.jf.dexlib2.iface.reference.FieldReference; 10 | import org.jf.dexlib2.util.ReferenceUtil; 11 | 12 | public class IGetOpFactory implements OpFactory { 13 | 14 | @Override 15 | public Op create(MethodLocation location, TIntObjectMap addressToLocation, VirtualMachine vm) { 16 | MethodLocation child = Utils.getNextLocation(location, addressToLocation); 17 | Instruction22c instr = (Instruction22c) location.getInstruction(); 18 | int destRegister = instr.getRegisterA(); 19 | int instanceRegister = instr.getRegisterB(); 20 | FieldReference reference = (FieldReference) instr.getReference(); 21 | String fieldDescriptor = ReferenceUtil.getFieldDescriptor(reference); 22 | 23 | return new IGetOp(location, child, destRegister, instanceRegister, fieldDescriptor, vm); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/opcode/IPutOp.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.opcode; 2 | 3 | import org.cf.smalivm.SideEffect; 4 | import org.cf.smalivm.VirtualMachine; 5 | import org.cf.smalivm.context.ExecutionContext; 6 | import org.cf.smalivm.context.ExecutionNode; 7 | import org.cf.smalivm.context.HeapItem; 8 | import org.cf.smalivm.context.MethodState; 9 | import org.jf.dexlib2.builder.MethodLocation; 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | 13 | public class IPutOp extends ExecutionContextOp { 14 | 15 | @SuppressWarnings("unused") 16 | private static final Logger log = LoggerFactory.getLogger(IPutOp.class.getSimpleName()); 17 | 18 | private final String fieldDescriptor; 19 | private final int valueRegister; 20 | private final int instanceRegister; 21 | private final VirtualMachine vm; 22 | 23 | IPutOp(MethodLocation location, MethodLocation child, int valueRegister, int instanceRegister, 24 | String fieldDescriptor, VirtualMachine vm) { 25 | super(location, child); 26 | 27 | this.valueRegister = valueRegister; 28 | this.instanceRegister = instanceRegister; 29 | this.fieldDescriptor = fieldDescriptor; 30 | this.vm = vm; 31 | } 32 | 33 | @Override 34 | public void execute(ExecutionNode node, ExecutionContext context) { 35 | MethodState mState = context.getMethodState(); 36 | HeapItem valueItem = mState.readRegister(valueRegister); 37 | HeapItem instanceItem = mState.readRegister(instanceRegister); 38 | 39 | mState.assignRegister(instanceRegister, instanceItem); 40 | } 41 | 42 | @Override 43 | public SideEffect.Level getSideEffectLevel() { 44 | return SideEffect.Level.WEAK; 45 | } 46 | 47 | @Override 48 | public String toString() { 49 | return getName() + " r" + valueRegister + ", r" + instanceRegister + ", " + fieldDescriptor; 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/opcode/IPutOpFactory.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.opcode; 2 | 3 | import gnu.trove.map.TIntObjectMap; 4 | 5 | import org.cf.smalivm.VirtualMachine; 6 | import org.cf.util.Utils; 7 | import org.jf.dexlib2.builder.MethodLocation; 8 | import org.jf.dexlib2.iface.instruction.formats.Instruction22c; 9 | import org.jf.dexlib2.iface.reference.FieldReference; 10 | import org.jf.dexlib2.util.ReferenceUtil; 11 | 12 | public class IPutOpFactory implements OpFactory { 13 | 14 | @Override 15 | public Op create(MethodLocation location, TIntObjectMap addressToLocation, VirtualMachine vm) { 16 | MethodLocation child = Utils.getNextLocation(location, addressToLocation); 17 | Instruction22c instr = (Instruction22c) location.getInstruction(); 18 | int valueRegister = instr.getRegisterA(); 19 | int instanceRegister = instr.getRegisterB(); 20 | FieldReference reference = (FieldReference) instr.getReference(); 21 | String fieldDescriptor = ReferenceUtil.getFieldDescriptor(reference); 22 | 23 | return new IPutOp(location, child, valueRegister, instanceRegister, fieldDescriptor, vm); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/opcode/InstanceOfOpFactory.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.opcode; 2 | 3 | import gnu.trove.map.TIntObjectMap; 4 | 5 | import org.cf.smalivm.VirtualMachine; 6 | import org.cf.smalivm.type.VirtualType; 7 | import org.cf.util.Utils; 8 | import org.jf.dexlib2.builder.MethodLocation; 9 | import org.jf.dexlib2.iface.instruction.formats.Instruction22c; 10 | import org.jf.dexlib2.iface.reference.TypeReference; 11 | 12 | public class InstanceOfOpFactory implements OpFactory { 13 | 14 | @Override 15 | public Op create(MethodLocation location, TIntObjectMap addressToLocation, VirtualMachine vm) { 16 | MethodLocation child = Utils.getNextLocation(location, addressToLocation); 17 | Instruction22c instr = (Instruction22c) location.getInstruction(); 18 | int destRegister = instr.getRegisterA(); 19 | int arg1Register = instr.getRegisterB(); 20 | TypeReference typeReference = (TypeReference) instr.getReference(); 21 | VirtualType referenceType = vm.getClassManager().getVirtualType(typeReference); 22 | 23 | return new InstanceOfOp(location, child, destRegister, arg1Register, referenceType, vm); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/opcode/MethodStateOp.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.opcode; 2 | 3 | import org.cf.smalivm.context.ExecutionNode; 4 | import org.cf.smalivm.context.MethodState; 5 | import org.jf.dexlib2.builder.MethodLocation; 6 | 7 | public abstract class MethodStateOp extends Op { 8 | 9 | MethodStateOp(MethodLocation location) { 10 | super(location, new MethodLocation[0]); 11 | } 12 | 13 | MethodStateOp(MethodLocation location, MethodLocation child) { 14 | super(location, child); 15 | } 16 | 17 | MethodStateOp(MethodLocation location, MethodLocation[] children) { 18 | super(location, children); 19 | } 20 | 21 | public abstract void execute(ExecutionNode executionNode, MethodState mState); 22 | 23 | } 24 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/opcode/MonitorEnterOp.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.opcode; 2 | 3 | import org.cf.smalivm.context.ExecutionNode; 4 | import org.cf.smalivm.context.MethodState; 5 | import org.jf.dexlib2.builder.MethodLocation; 6 | 7 | public class MonitorEnterOp extends MethodStateOp { 8 | 9 | private final int destRegister; 10 | 11 | MonitorEnterOp(MethodLocation location, MethodLocation child, int destRegister) { 12 | super(location, child); 13 | this.destRegister = destRegister; 14 | } 15 | 16 | @Override 17 | public void execute(ExecutionNode node, MethodState mState) { 18 | } 19 | 20 | @Override 21 | public String toString() { 22 | return getName() + " r" + destRegister; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/opcode/MonitorEnterOpFactory.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.opcode; 2 | 3 | import gnu.trove.map.TIntObjectMap; 4 | 5 | import org.cf.smalivm.VirtualMachine; 6 | import org.cf.util.Utils; 7 | import org.jf.dexlib2.builder.BuilderInstruction; 8 | import org.jf.dexlib2.builder.MethodLocation; 9 | import org.jf.dexlib2.iface.instruction.OneRegisterInstruction; 10 | 11 | public class MonitorEnterOpFactory implements OpFactory { 12 | 13 | @Override 14 | public Op create(MethodLocation location, TIntObjectMap addressToLocation, VirtualMachine vm) { 15 | MethodLocation child = Utils.getNextLocation(location, addressToLocation); 16 | BuilderInstruction instruction = (BuilderInstruction) location.getInstruction(); 17 | int destRegister = ((OneRegisterInstruction) instruction).getRegisterA(); 18 | 19 | return new MonitorEnterOp(location, child, destRegister); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/opcode/MonitorExitOp.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.opcode; 2 | 3 | import org.cf.smalivm.context.ExecutionNode; 4 | import org.cf.smalivm.context.MethodState; 5 | import org.jf.dexlib2.builder.MethodLocation; 6 | 7 | public class MonitorExitOp extends MethodStateOp { 8 | 9 | private final int destRegister; 10 | 11 | MonitorExitOp(MethodLocation location, MethodLocation child, int destRegister) { 12 | super(location, child); 13 | this.destRegister = destRegister; 14 | } 15 | 16 | @Override 17 | public void execute(ExecutionNode node, MethodState mState) { 18 | } 19 | 20 | @Override 21 | public String toString() { 22 | return getName() + " r" + destRegister; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/opcode/MonitorExitOpFactory.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.opcode; 2 | 3 | import gnu.trove.map.TIntObjectMap; 4 | 5 | import org.cf.smalivm.VirtualMachine; 6 | import org.cf.util.Utils; 7 | import org.jf.dexlib2.builder.BuilderInstruction; 8 | import org.jf.dexlib2.builder.MethodLocation; 9 | import org.jf.dexlib2.iface.instruction.OneRegisterInstruction; 10 | 11 | public class MonitorExitOpFactory implements OpFactory { 12 | 13 | @Override 14 | public Op create(MethodLocation location, TIntObjectMap addressToLocation, VirtualMachine vm) { 15 | MethodLocation child = Utils.getNextLocation(location, addressToLocation); 16 | BuilderInstruction instruction = (BuilderInstruction) location.getInstruction(); 17 | int destRegister = ((OneRegisterInstruction) instruction).getRegisterA(); 18 | 19 | return new MonitorExitOp(location, child, destRegister); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/opcode/MoveOpFactory.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.opcode; 2 | 3 | import gnu.trove.map.TIntObjectMap; 4 | 5 | import org.cf.smalivm.VirtualMachine; 6 | import org.cf.smalivm.opcode.MoveOp.MoveType; 7 | import org.cf.util.Utils; 8 | import org.jf.dexlib2.builder.BuilderInstruction; 9 | import org.jf.dexlib2.builder.MethodLocation; 10 | import org.jf.dexlib2.iface.instruction.OneRegisterInstruction; 11 | import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction; 12 | 13 | public class MoveOpFactory implements OpFactory { 14 | 15 | private static MoveType getMoveType(String opName) { 16 | if (opName.contains("-result")) { 17 | return MoveType.RESULT; 18 | } else if (opName.contains("-exception")) { 19 | return MoveType.EXCEPTION; 20 | } else { 21 | return MoveType.REGISTER; 22 | } 23 | } 24 | 25 | @Override 26 | public Op create(MethodLocation location, TIntObjectMap addressToLocation, VirtualMachine vm) { 27 | MethodLocation child = Utils.getNextLocation(location, addressToLocation); 28 | BuilderInstruction instruction = (BuilderInstruction) location.getInstruction(); 29 | String opName = instruction.getOpcode().name; 30 | int toRegister = ((OneRegisterInstruction) instruction).getRegisterA(); 31 | MoveType moveType = getMoveType(opName); 32 | switch (moveType) { 33 | case RESULT: 34 | case EXCEPTION: 35 | return new MoveOp(location, child, toRegister, moveType); 36 | case REGISTER: 37 | int targetRegister = ((TwoRegisterInstruction) instruction).getRegisterB(); 38 | return new MoveOp(location, child, toRegister, targetRegister); 39 | default: 40 | return null; 41 | } 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/opcode/NewArrayOpFactory.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.opcode; 2 | 3 | import gnu.trove.map.TIntObjectMap; 4 | 5 | import org.cf.smalivm.VirtualMachine; 6 | import org.cf.util.Utils; 7 | import org.jf.dexlib2.builder.MethodLocation; 8 | import org.jf.dexlib2.iface.instruction.formats.Instruction22c; 9 | import org.jf.dexlib2.util.ReferenceUtil; 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | 13 | public class NewArrayOpFactory implements OpFactory { 14 | 15 | @SuppressWarnings("unused") 16 | private static final Logger log = LoggerFactory.getLogger(NewArrayOpFactory.class.getSimpleName()); 17 | 18 | @Override 19 | public NewArrayOp create(MethodLocation location, TIntObjectMap addressToLocation, VirtualMachine vm) { 20 | MethodLocation child = Utils.getNextLocation(location, addressToLocation); 21 | Instruction22c instr = (Instruction22c) location.getInstruction(); 22 | int destRegister = instr.getRegisterA(); 23 | int sizeRegister = instr.getRegisterB(); 24 | String arrayType = ReferenceUtil.getReferenceString(instr.getReference()); 25 | 26 | return new NewArrayOp(location, child, destRegister, sizeRegister, arrayType, vm.getClassLoader()); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/opcode/NewInstanceOp.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.opcode; 2 | 3 | import org.cf.smalivm.SideEffect; 4 | import org.cf.smalivm.VirtualMachine; 5 | import org.cf.smalivm.context.ExecutionContext; 6 | import org.cf.smalivm.context.ExecutionNode; 7 | import org.cf.smalivm.context.HeapItem; 8 | import org.cf.smalivm.context.MethodState; 9 | import org.cf.smalivm.type.VirtualClass; 10 | import org.cf.smalivm.type.UninitializedInstance; 11 | import org.jf.dexlib2.builder.MethodLocation; 12 | 13 | public class NewInstanceOp extends ExecutionContextOp { 14 | 15 | private final VirtualClass virtualClass; 16 | private final int destRegister; 17 | private final VirtualMachine vm; 18 | private SideEffect.Level sideEffectLevel; 19 | 20 | NewInstanceOp(MethodLocation location, MethodLocation child, int destRegister, VirtualClass virtualClass, 21 | VirtualMachine vm) { 22 | super(location, child); 23 | 24 | this.destRegister = destRegister; 25 | this.virtualClass = virtualClass; 26 | this.vm = vm; 27 | sideEffectLevel = SideEffect.Level.STRONG; 28 | } 29 | 30 | @Override 31 | public void execute(ExecutionNode node, ExecutionContext context) { 32 | Object instance = new UninitializedInstance(virtualClass); 33 | if (vm.isSafe(virtualClass)) { 34 | sideEffectLevel = SideEffect.Level.NONE; 35 | } else { 36 | // New-instance causes static initialization (but not new-array!) 37 | context.readClassState(virtualClass); // access will initialize if necessary 38 | sideEffectLevel = context.getClassSideEffectLevel(virtualClass); 39 | } 40 | 41 | MethodState mState = context.getMethodState(); 42 | HeapItem instanceItem = new HeapItem(instance, virtualClass.getName()); 43 | mState.assignRegister(destRegister, instanceItem); 44 | } 45 | 46 | @Override 47 | public SideEffect.Level getSideEffectLevel() { 48 | return sideEffectLevel; 49 | } 50 | 51 | @Override 52 | public String toString() { 53 | return getName() + " r" + destRegister + ", " + virtualClass; 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/opcode/NewInstanceOpFactory.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.opcode; 2 | 3 | import gnu.trove.map.TIntObjectMap; 4 | 5 | import org.cf.smalivm.VirtualMachine; 6 | import org.cf.smalivm.type.VirtualClass; 7 | import org.cf.util.Utils; 8 | import org.jf.dexlib2.builder.MethodLocation; 9 | import org.jf.dexlib2.iface.instruction.formats.Instruction21c; 10 | import org.jf.dexlib2.iface.reference.TypeReference; 11 | 12 | public class NewInstanceOpFactory implements OpFactory { 13 | 14 | @Override 15 | public Op create(MethodLocation location, TIntObjectMap addressToLocation, VirtualMachine vm) { 16 | MethodLocation child = Utils.getNextLocation(location, addressToLocation); 17 | Instruction21c instr = (Instruction21c) location.getInstruction(); 18 | int destRegister = instr.getRegisterA(); 19 | TypeReference typeRef = (TypeReference) instr.getReference(); 20 | String className = typeRef.getType(); 21 | VirtualClass virtualClass = vm.getClassManager().getVirtualClass(className); 22 | 23 | return new NewInstanceOp(location, child, destRegister, virtualClass, vm); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/opcode/NopOp.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.opcode; 2 | 3 | import org.cf.smalivm.context.ExecutionNode; 4 | import org.cf.smalivm.context.MethodState; 5 | import org.jf.dexlib2.builder.MethodLocation; 6 | 7 | public class NopOp extends MethodStateOp { 8 | 9 | NopOp(MethodLocation location, MethodLocation child) { 10 | super(location, child); 11 | } 12 | 13 | @Override 14 | public void execute(ExecutionNode node, MethodState mState) { 15 | // Yesterday, upon the stair, 16 | // I met an op who wasn't there. 17 | // It wasn't there again today, 18 | // I wish, I wish it'd go away... 19 | // 20 | // Last night I saw upon the stair, 21 | // A little op who wasn't there, 22 | // It wasn't there again today 23 | // Oh, how I wish it'd go away... 24 | } 25 | 26 | @Override 27 | public String toString() { 28 | return getName(); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/opcode/NopOpFactory.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.opcode; 2 | 3 | import gnu.trove.map.TIntObjectMap; 4 | 5 | import org.cf.smalivm.VirtualMachine; 6 | import org.cf.util.Utils; 7 | import org.jf.dexlib2.builder.MethodLocation; 8 | 9 | public class NopOpFactory implements OpFactory { 10 | 11 | @Override 12 | public Op create(MethodLocation location, TIntObjectMap addressToLocation, VirtualMachine vm) { 13 | MethodLocation child = Utils.getNextLocation(location, addressToLocation); 14 | 15 | return new NopOp(location, child); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/opcode/Op.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.opcode; 2 | 3 | import java.util.HashSet; 4 | import java.util.Set; 5 | 6 | import org.cf.smalivm.SideEffect; 7 | import org.jf.dexlib2.builder.BuilderInstruction; 8 | import org.jf.dexlib2.builder.MethodLocation; 9 | 10 | public abstract class Op { 11 | 12 | private final MethodLocation location; 13 | private final MethodLocation[] children; 14 | private final Set exceptions; 15 | 16 | Op(MethodLocation location, MethodLocation child) { 17 | this(location, new MethodLocation[] { child }); 18 | } 19 | 20 | Op(MethodLocation location, MethodLocation[] children) { 21 | this.location = location; 22 | this.children = children; 23 | exceptions = new HashSet<>(); 24 | } 25 | 26 | public final int getAddress() { 27 | return location.getCodeAddress(); 28 | } 29 | 30 | public final int getIndex() { 31 | return location.getIndex(); 32 | } 33 | 34 | public final MethodLocation[] getChildren() { 35 | return children; 36 | } 37 | 38 | public Set getExceptions() { 39 | return exceptions; 40 | } 41 | 42 | public final BuilderInstruction getInstruction() { 43 | return (BuilderInstruction) location.getInstruction(); 44 | } 45 | 46 | public final MethodLocation getLocation() { 47 | return location; 48 | } 49 | 50 | public final String getName() { 51 | if (getInstruction() != null) { 52 | return getInstruction().getOpcode().name; 53 | } else { 54 | // Happens during instruction removal 55 | return "*null instr*"; 56 | } 57 | } 58 | 59 | public SideEffect.Level getSideEffectLevel() { 60 | return SideEffect.Level.NONE; 61 | } 62 | 63 | @Override 64 | public abstract String toString(); 65 | 66 | void addException(Throwable exception) { 67 | exceptions.add(exception); 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/opcode/OpFactory.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.opcode; 2 | 3 | import gnu.trove.map.TIntObjectMap; 4 | 5 | import org.cf.smalivm.VirtualMachine; 6 | import org.jf.dexlib2.builder.MethodLocation; 7 | 8 | public interface OpFactory { 9 | 10 | Op create(MethodLocation location, TIntObjectMap addressToLocation, VirtualMachine vm); 11 | } 12 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/opcode/ReturnOp.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.opcode; 2 | 3 | import org.cf.smalivm.context.ExecutionNode; 4 | import org.cf.smalivm.context.HeapItem; 5 | import org.cf.smalivm.context.MethodState; 6 | import org.jf.dexlib2.builder.MethodLocation; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | public class ReturnOp extends MethodStateOp { 11 | 12 | @SuppressWarnings("unused") 13 | private static final Logger log = LoggerFactory.getLogger(ReturnOp.class.getSimpleName()); 14 | 15 | private final int register; 16 | 17 | ReturnOp(MethodLocation location, int register) { 18 | super(location); 19 | 20 | this.register = register; 21 | } 22 | 23 | @Override 24 | public void execute(ExecutionNode node, MethodState mState) { 25 | HeapItem item = mState.readRegister(register); 26 | mState.assignReturnRegister(item); 27 | } 28 | 29 | @Override 30 | public String toString() { 31 | return getName() + " r" + register; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/opcode/ReturnOpFactory.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.opcode; 2 | 3 | import gnu.trove.map.TIntObjectMap; 4 | 5 | import org.cf.smalivm.VirtualMachine; 6 | import org.jf.dexlib2.builder.MethodLocation; 7 | import org.jf.dexlib2.iface.instruction.formats.Instruction11x; 8 | 9 | public class ReturnOpFactory implements OpFactory { 10 | 11 | @Override 12 | public Op create(MethodLocation location, TIntObjectMap addressToLocation, VirtualMachine vm) { 13 | Instruction11x instr = (Instruction11x) location.getInstruction(); 14 | int register = instr.getRegisterA(); 15 | 16 | return new ReturnOp(location, register); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/opcode/ReturnVoidOp.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.opcode; 2 | 3 | import org.cf.smalivm.context.ExecutionNode; 4 | import org.cf.smalivm.context.MethodState; 5 | import org.jf.dexlib2.builder.MethodLocation; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | public class ReturnVoidOp extends MethodStateOp { 10 | 11 | @SuppressWarnings("unused") 12 | private static final Logger log = LoggerFactory.getLogger(ReturnVoidOp.class.getSimpleName()); 13 | 14 | ReturnVoidOp(MethodLocation location) { 15 | super(location); 16 | } 17 | 18 | @Override 19 | public void execute(ExecutionNode node, MethodState mState) { 20 | // 21 | } 22 | 23 | @Override 24 | public String toString() { 25 | return getName(); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/opcode/ReturnVoidOpFactory.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.opcode; 2 | 3 | import gnu.trove.map.TIntObjectMap; 4 | 5 | import org.cf.smalivm.VirtualMachine; 6 | import org.jf.dexlib2.builder.MethodLocation; 7 | 8 | public class ReturnVoidOpFactory implements OpFactory { 9 | 10 | @Override 11 | public Op create(MethodLocation location, TIntObjectMap addressToLocation, VirtualMachine vm) { 12 | return new ReturnVoidOp(location); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/opcode/SGetOp.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.opcode; 2 | 3 | import org.cf.smalivm.StaticFieldAccessor; 4 | import org.cf.smalivm.VirtualMachine; 5 | import org.cf.smalivm.context.ExecutionContext; 6 | import org.cf.smalivm.context.ExecutionNode; 7 | import org.cf.smalivm.context.HeapItem; 8 | import org.cf.smalivm.context.MethodState; 9 | import org.cf.smalivm.type.VirtualField; 10 | import org.jf.dexlib2.builder.MethodLocation; 11 | import org.jf.dexlib2.iface.reference.FieldReference; 12 | import org.jf.dexlib2.util.ReferenceUtil; 13 | import org.slf4j.Logger; 14 | import org.slf4j.LoggerFactory; 15 | 16 | public class SGetOp extends ExecutionContextOp { 17 | 18 | @SuppressWarnings("unused") 19 | private static final Logger log = LoggerFactory.getLogger(SGetOp.class.getSimpleName()); 20 | 21 | private final int destRegister; 22 | private final FieldReference fieldReference; 23 | private final VirtualField actualField; 24 | private final VirtualMachine vm; 25 | 26 | SGetOp(MethodLocation location, MethodLocation child, int destRegister, FieldReference fieldReference, 27 | VirtualField actualField, VirtualMachine vm) { 28 | super(location, child); 29 | 30 | this.destRegister = destRegister; 31 | this.fieldReference = fieldReference; 32 | this.actualField = actualField; 33 | this.vm = vm; 34 | } 35 | 36 | @Override 37 | public void execute(ExecutionNode node, ExecutionContext context) { 38 | StaticFieldAccessor accessor = vm.getStaticFieldAccessor(); 39 | HeapItem item = accessor.getField(context, actualField); 40 | MethodState mState = context.getMethodState(); 41 | mState.assignRegister(destRegister, item); 42 | } 43 | 44 | @Override 45 | public String toString() { 46 | return getName() + " r" + destRegister + ", " + ReferenceUtil.getFieldDescriptor(fieldReference); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/opcode/SGetOpFactory.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.opcode; 2 | 3 | import gnu.trove.map.TIntObjectMap; 4 | 5 | import org.cf.smalivm.VirtualMachine; 6 | import org.cf.smalivm.type.VirtualClass; 7 | import org.cf.smalivm.type.VirtualField; 8 | import org.cf.util.Utils; 9 | import org.jf.dexlib2.builder.MethodLocation; 10 | import org.jf.dexlib2.iface.instruction.formats.Instruction21c; 11 | import org.jf.dexlib2.iface.reference.FieldReference; 12 | 13 | public class SGetOpFactory implements OpFactory { 14 | 15 | @Override 16 | public Op create(MethodLocation location, TIntObjectMap addressToLocation, VirtualMachine vm) { 17 | MethodLocation child = Utils.getNextLocation(location, addressToLocation); 18 | Instruction21c instr = (Instruction21c) location.getInstruction(); 19 | int destRegister = instr.getRegisterA(); 20 | FieldReference fieldReference = (FieldReference) instr.getReference(); 21 | VirtualClass fieldClass = vm.getClassManager().getVirtualClass(fieldReference.getDefiningClass()); 22 | VirtualField actualField = fieldClass.getField(fieldReference.getName()); 23 | 24 | return new SGetOp(location, child, destRegister, fieldReference, actualField, vm); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/opcode/SPutOpFactory.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.opcode; 2 | 3 | import gnu.trove.map.TIntObjectMap; 4 | 5 | import org.cf.smalivm.VirtualMachine; 6 | import org.cf.smalivm.type.VirtualClass; 7 | import org.cf.smalivm.type.VirtualField; 8 | import org.cf.util.Utils; 9 | import org.jf.dexlib2.builder.MethodLocation; 10 | import org.jf.dexlib2.iface.instruction.formats.Instruction21c; 11 | import org.jf.dexlib2.iface.reference.FieldReference; 12 | 13 | public class SPutOpFactory implements OpFactory { 14 | 15 | @Override 16 | public Op create(MethodLocation location, TIntObjectMap addressToLocation, VirtualMachine vm) { 17 | MethodLocation child = Utils.getNextLocation(location, addressToLocation); 18 | Instruction21c instr = (Instruction21c) location.getInstruction(); 19 | int destRegister = instr.getRegisterA(); 20 | FieldReference fieldReference = (FieldReference) instr.getReference(); 21 | VirtualClass fieldClass = vm.getClassManager().getVirtualClass(fieldReference.getDefiningClass()); 22 | VirtualField actualField = fieldClass.getField(fieldReference.getName()); 23 | 24 | return new SPutOp(location, child, destRegister, fieldReference, actualField, vm); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/opcode/SwitchOp.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.opcode; 2 | 3 | import org.cf.smalivm.context.ExecutionNode; 4 | import org.cf.smalivm.context.HeapItem; 5 | import org.cf.smalivm.context.MethodState; 6 | import org.jf.dexlib2.builder.MethodLocation; 7 | 8 | public class SwitchOp extends MethodStateOp { 9 | 10 | private final MethodLocation child; 11 | private final int register; 12 | 13 | SwitchOp(MethodLocation location, MethodLocation child, MethodLocation target, int register) { 14 | super(location, target); 15 | 16 | this.child = child; 17 | this.register = register; 18 | } 19 | 20 | @Override 21 | public void execute(ExecutionNode node, MethodState mState) { 22 | // Use result register to store value to compare. Comparison is handled by payload op. 23 | HeapItem item = mState.readRegister(register); 24 | mState.assignResultRegister(item); 25 | 26 | // If switch "falls through", will need the immediate op after this. 27 | mState.setPseudoInstructionReturnLocation(child); 28 | } 29 | 30 | @Override 31 | public String toString() { 32 | return getName() + " r" + register + ", :addr_" + getChildren()[0].getCodeAddress(); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/opcode/SwitchOpFactory.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.opcode; 2 | 3 | import gnu.trove.map.TIntObjectMap; 4 | 5 | import org.cf.smalivm.VirtualMachine; 6 | import org.cf.util.Utils; 7 | import org.jf.dexlib2.builder.MethodLocation; 8 | import org.jf.dexlib2.iface.instruction.OffsetInstruction; 9 | import org.jf.dexlib2.iface.instruction.formats.Instruction31t; 10 | 11 | public class SwitchOpFactory implements OpFactory { 12 | 13 | @Override 14 | public Op create(MethodLocation location, TIntObjectMap addressToLocation, VirtualMachine vm) { 15 | MethodLocation child = Utils.getNextLocation(location, addressToLocation); 16 | int address = location.getCodeAddress(); 17 | int branchOffset = ((OffsetInstruction) location.getInstruction()).getCodeOffset(); 18 | int targetAddress = address + branchOffset; 19 | MethodLocation target = addressToLocation.get(targetAddress); 20 | Instruction31t instr = (Instruction31t) location.getInstruction(); 21 | int register = instr.getRegisterA(); 22 | 23 | return new SwitchOp(location, child, target, register); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/opcode/SwitchPayloadOpFactory.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.opcode; 2 | 3 | import gnu.trove.map.TIntIntMap; 4 | import gnu.trove.map.TIntObjectMap; 5 | import gnu.trove.map.hash.TIntIntHashMap; 6 | 7 | import org.cf.smalivm.VirtualMachine; 8 | import org.jf.dexlib2.builder.MethodLocation; 9 | import org.jf.dexlib2.iface.instruction.SwitchElement; 10 | import org.jf.dexlib2.iface.instruction.SwitchPayload; 11 | 12 | public class SwitchPayloadOpFactory implements OpFactory { 13 | 14 | @Override 15 | public Op create(MethodLocation location, TIntObjectMap addressToLocation, VirtualMachine vm) { 16 | SwitchPayload instr = (SwitchPayload) location.getInstruction(); 17 | TIntIntMap targetKeyToOffset = new TIntIntHashMap(); 18 | for (SwitchElement element : instr.getSwitchElements()) { 19 | targetKeyToOffset.put(element.getKey(), element.getOffset()); 20 | } 21 | 22 | return new SwitchPayloadOp(location, addressToLocation, targetKeyToOffset); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/opcode/ThrowOp.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.opcode; 2 | 3 | import org.cf.smalivm.context.ExecutionNode; 4 | import org.cf.smalivm.context.HeapItem; 5 | import org.cf.smalivm.context.MethodState; 6 | import org.jf.dexlib2.builder.MethodLocation; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | public class ThrowOp extends MethodStateOp { 11 | 12 | @SuppressWarnings("unused") 13 | private static final Logger log = LoggerFactory.getLogger(ThrowOp.class.getSimpleName()); 14 | 15 | private final int register; 16 | 17 | ThrowOp(MethodLocation location, int register) { 18 | super(location); 19 | 20 | this.register = register; 21 | } 22 | 23 | @Override 24 | public void execute(ExecutionNode node, MethodState mState) { 25 | HeapItem item = mState.readRegister(register); 26 | mState.assignThrowRegister(item); 27 | } 28 | 29 | @Override 30 | public String toString() { 31 | return getName() + " r" + register; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/opcode/ThrowOpFactory.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.opcode; 2 | 3 | import gnu.trove.map.TIntObjectMap; 4 | 5 | import org.cf.smalivm.VirtualMachine; 6 | import org.jf.dexlib2.builder.MethodLocation; 7 | import org.jf.dexlib2.iface.instruction.formats.Instruction11x; 8 | 9 | public class ThrowOpFactory implements OpFactory { 10 | 11 | @Override 12 | public Op create(MethodLocation location, TIntObjectMap addressToLocation, VirtualMachine vm) { 13 | Instruction11x instr = (Instruction11x) location.getInstruction(); 14 | int register = instr.getRegisterA(); 15 | 16 | return new ThrowOp(location, register); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/opcode/UnaryMathOpFactory.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.opcode; 2 | 3 | import gnu.trove.map.TIntObjectMap; 4 | 5 | import org.cf.smalivm.VirtualMachine; 6 | import org.cf.util.Utils; 7 | import org.jf.dexlib2.builder.MethodLocation; 8 | import org.jf.dexlib2.iface.instruction.formats.Instruction12x; 9 | 10 | public class UnaryMathOpFactory implements OpFactory { 11 | 12 | @Override 13 | public Op create(MethodLocation location, TIntObjectMap addressToLocation, VirtualMachine vm) { 14 | MethodLocation child = Utils.getNextLocation(location, addressToLocation); 15 | Instruction12x instr = (Instruction12x) location.getInstruction(); 16 | int destRegister = instr.getRegisterA(); 17 | int srcRegister = instr.getRegisterB(); 18 | 19 | return new UnaryMathOp(location, child, destRegister, srcRegister); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/type/InitializedInstance.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.type; 2 | 3 | import org.apache.commons.lang3.builder.EqualsBuilder; 4 | import org.apache.commons.lang3.builder.HashCodeBuilder; 5 | import org.cf.smalivm.context.InstanceState; 6 | 7 | /** 8 | * Represents an object instance of a virtual defined by a local class such as an input or framework class. 9 | */ 10 | public class InitializedInstance extends Instance { 11 | 12 | private InstanceState iState; 13 | 14 | public InitializedInstance(VirtualType type) { 15 | super(type); 16 | iState = null; 17 | } 18 | 19 | public InstanceState getState() { 20 | return iState; 21 | } 22 | 23 | @Override 24 | public int hashCode() { 25 | return new HashCodeBuilder(223, 197).append(getType()).append(getState()).hashCode(); 26 | } 27 | 28 | @Override 29 | public boolean equals(Object other) { 30 | if (other == null) { 31 | return false; 32 | } else if (other == this) { 33 | return true; 34 | } else if (!(other instanceof InitializedInstance)) { 35 | return false; 36 | } 37 | 38 | InitializedInstance rhs = (InitializedInstance) other; 39 | 40 | return new EqualsBuilder().append(getType(), rhs.getType()).append(getState(), rhs.getState()).isEquals(); 41 | } 42 | 43 | public boolean isInitialized() { 44 | return getState() == null; 45 | } 46 | 47 | public void setContext(InstanceState iState) { 48 | this.iState = iState; 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/type/Instance.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.type; 2 | 3 | public abstract class Instance { 4 | 5 | private final VirtualType type; 6 | 7 | protected Instance(VirtualType type) { 8 | this.type = type; 9 | } 10 | 11 | public VirtualType getType() { 12 | return type; 13 | } 14 | 15 | public String toString() { 16 | return getType().getName(); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/type/UninitializedInstance.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.type; 2 | 3 | import org.apache.commons.lang3.builder.EqualsBuilder; 4 | import org.apache.commons.lang3.builder.HashCodeBuilder; 5 | 6 | public class UninitializedInstance extends Instance { 7 | 8 | public UninitializedInstance(VirtualType type) { 9 | super(type); 10 | } 11 | 12 | @Override 13 | public int hashCode() { 14 | return new HashCodeBuilder(337, 97).append(getType()).hashCode(); 15 | } 16 | 17 | @Override 18 | public boolean equals(Object other) { 19 | if (other == null) { 20 | return false; 21 | } else if (other == this) { 22 | return true; 23 | } else if (other.getClass() != getClass()) { 24 | return false; 25 | } 26 | UninitializedInstance rhs = (UninitializedInstance) other; 27 | 28 | return new EqualsBuilder().append(getType(), rhs.getType()).isEquals(); 29 | } 30 | 31 | @Override 32 | public String toString() { 33 | return "Uninitialized " + getType(); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/type/UnknownValue.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.type; 2 | 3 | public class UnknownValue extends Instance { 4 | 5 | public UnknownValue() { 6 | super(null); 7 | } 8 | 9 | @Override 10 | public int hashCode() { 11 | return 0; 12 | } 13 | 14 | @Override 15 | public boolean equals(Object other) { 16 | // This is similar to NULL != NULL 17 | return false; 18 | } 19 | 20 | @Override 21 | public String toString() { 22 | return "*unknown*"; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/type/VirtualClassItem.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.type; 2 | 3 | import org.jf.dexlib2.iface.reference.Reference; 4 | 5 | public abstract class VirtualClassItem { 6 | 7 | private final Reference reference; 8 | private final VirtualType definingClass; 9 | 10 | protected VirtualClassItem(Reference reference, VirtualType definingClass) { 11 | this.reference = reference; 12 | this.definingClass = definingClass; 13 | } 14 | 15 | public final String getBinaryClassName() { 16 | return getDefiningClass().getBinaryName(); 17 | } 18 | 19 | public final String getClassName() { 20 | return getDefiningClass().getName(); 21 | } 22 | 23 | public VirtualType getDefiningClass() { 24 | return definingClass; 25 | } 26 | 27 | public abstract String getName(); 28 | 29 | public abstract String getSignature(); 30 | 31 | public final String getSourceClassName() { 32 | return getDefiningClass().getSourceName(); 33 | } 34 | 35 | @Override 36 | public String toString() { 37 | return getSignature(); 38 | } 39 | 40 | 41 | } 42 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/type/VirtualMethod.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.type; 2 | 3 | import org.jf.dexlib2.builder.BuilderTryBlock; 4 | import org.jf.dexlib2.builder.MutableMethodImplementation; 5 | import org.jf.dexlib2.iface.reference.Reference; 6 | import org.jf.dexlib2.writer.builder.BuilderMethod; 7 | 8 | import java.util.List; 9 | 10 | public abstract class VirtualMethod extends VirtualClassItem { 11 | 12 | VirtualMethod(Reference reference, VirtualType type) { 13 | super(reference, type); 14 | } 15 | 16 | public abstract MutableMethodImplementation getImplementation(); 17 | 18 | public abstract BuilderMethod getMethodDefinition(); 19 | 20 | public final String getDescriptor() { 21 | return getSignature().split("->")[1]; 22 | } 23 | 24 | public abstract int getParameterSize(); 25 | 26 | public abstract List getParameterTypeNames(); 27 | 28 | public abstract int getRegisterCount(); 29 | 30 | public abstract String getReturnType(); 31 | 32 | public abstract List getTryBlocks(); 33 | 34 | public abstract boolean hasImplementation(); 35 | 36 | public abstract boolean isNative(); 37 | 38 | public abstract boolean isStatic(); 39 | 40 | public abstract boolean isFinal(); 41 | 42 | public abstract boolean returnsVoid(); 43 | 44 | } 45 | -------------------------------------------------------------------------------- /smalivm/src/main/java/org/cf/smalivm/type/VirtualPrimitive.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.type; 2 | 3 | import org.cf.util.ClassNameUtils; 4 | import org.jf.dexlib2.iface.reference.TypeReference; 5 | 6 | import java.util.Collection; 7 | import java.util.Collections; 8 | import java.util.Set; 9 | 10 | public class VirtualPrimitive extends VirtualType { 11 | 12 | VirtualPrimitive(TypeReference typeReference) { 13 | super(typeReference, typeReference.getType(), ClassNameUtils.internalToBinary(typeReference.getType()), 14 | ClassNameUtils.internalToSource(typeReference.getType())); 15 | } 16 | 17 | @Override 18 | public Set getImmediateAncestors() { 19 | return Collections.emptySet(); 20 | } 21 | 22 | @Override 23 | public Set getAncestors() { 24 | return Collections.emptySet(); 25 | } 26 | 27 | @Override 28 | public Collection getFields() { 29 | return Collections.emptyList(); 30 | } 31 | 32 | @Override 33 | public Collection getMethods() { 34 | return Collections.emptyList(); 35 | } 36 | 37 | @Override 38 | public boolean instanceOf(VirtualType targetType) { 39 | // Not technically possible with primitives; will fail verification 40 | // But used to determine if primitive can fit in array 41 | return equals(targetType); 42 | } 43 | 44 | @Override 45 | public boolean isArray() { 46 | return false; 47 | } 48 | 49 | @Override 50 | public boolean isPrimitive() { 51 | return true; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /smalivm/src/main/resources/framework/android-framework.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CalebFenton/simplify/29fb25d624aecf0b075dea5c6029b2541474ddfe/smalivm/src/main/resources/framework/android-framework.jar -------------------------------------------------------------------------------- /smalivm/src/main/resources/props/android-27-emu/data/local.prop: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CalebFenton/simplify/29fb25d624aecf0b075dea5c6029b2541474ddfe/smalivm/src/main/resources/props/android-27-emu/data/local.prop -------------------------------------------------------------------------------- /smalivm/src/main/resources/props/android-27-emu/default.prop: -------------------------------------------------------------------------------- 1 | # 2 | # ADDITIONAL_DEFAULT_PROPERTIES 3 | # 4 | ro.secure=1 5 | security.perf_harden=1 6 | ro.allow.mock.location=0 7 | ro.debuggable=1 8 | # 9 | # BOOTIMAGE_BUILD_PROPERTIES 10 | # 11 | ro.bootimage.build.date=Tue Apr 24 21:52:13 UTC 2018 12 | ro.bootimage.build.date.utc=1524606733 13 | ro.bootimage.build.fingerprint=google/sdk_gphone_x86/generic_x86:8.1.0/OSM1.180201.021/4741582:userdebug/dev-keys 14 | persist.sys.usb.config=adb 15 | -------------------------------------------------------------------------------- /smalivm/src/main/resources/props/android-27-emu/system/build.prop: -------------------------------------------------------------------------------- 1 | 2 | # begin build properties 3 | # autogenerated by buildinfo.sh 4 | ro.build.id=OSM1.180201.021 5 | ro.build.display.id=sdk_gphone_x86-userdebug 8.1.0 OSM1.180201.021 4741582 dev-keys 6 | ro.build.version.incremental=4741582 7 | ro.build.version.sdk=27 8 | ro.build.version.preview_sdk=0 9 | ro.build.version.codename=REL 10 | ro.build.version.all_codenames=REL 11 | ro.build.version.release=8.1.0 12 | ro.build.version.security_patch=2018-01-05 13 | ro.build.version.base_os= 14 | ro.build.date=Tue Apr 24 21:52:13 UTC 2018 15 | ro.build.date.utc=1524606733 16 | ro.build.type=userdebug 17 | ro.build.user=android-build 18 | ro.build.host=abfarm335 19 | ro.build.tags=dev-keys 20 | ro.build.flavor=sdk_gphone_x86-userdebug 21 | ro.product.model=Android SDK built for x86 22 | ro.product.brand=google 23 | ro.product.name=sdk_gphone_x86 24 | ro.product.device=generic_x86 25 | # ro.product.cpu.abi and ro.product.cpu.abi2 are obsolete, 26 | # use ro.product.cpu.abilist instead. 27 | ro.product.cpu.abi=x86 28 | ro.product.cpu.abilist=x86 29 | ro.product.cpu.abilist32=x86 30 | ro.product.cpu.abilist64= 31 | ro.product.manufacturer=Google 32 | ro.product.locale=en-US 33 | ro.wifi.channels= 34 | # ro.build.product is obsolete; use ro.product.device 35 | ro.build.product=generic_x86 36 | # Do not try to parse description, fingerprint, or thumbprint 37 | ro.build.description=sdk_gphone_x86-userdebug 8.1.0 OSM1.180201.021 4741582 dev-keys 38 | ro.build.fingerprint=google/sdk_gphone_x86/generic_x86:8.1.0/OSM1.180201.021/4741582:userdebug/dev-keys 39 | ro.build.characteristics=emulator 40 | # end build properties 41 | # 42 | # from build/target/board/generic_x86/system.prop 43 | # 44 | # 45 | # system.prop for generic sdk 46 | # 47 | 48 | rild.libpath=/vendor/lib/libreference-ril.so 49 | 50 | # 51 | # ADDITIONAL_BUILD_PROPERTIES 52 | # 53 | ro.bionic.ld.warning=1 54 | ro.treble.enabled=true 55 | persist.sys.dalvik.vm.lib.2=libart.so 56 | dalvik.vm.isa.x86.variant=x86 57 | dalvik.vm.isa.x86.features=default 58 | dalvik.vm.lockprof.threshold=500 59 | xmpp.auto-presence=true 60 | ro.config.nocheckin=yes 61 | net.bt.name=Android 62 | dalvik.vm.stack-trace-dir=/data/anr 63 | -------------------------------------------------------------------------------- /smalivm/src/main/resources/props/android-27-emu/system/default.prop: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CalebFenton/simplify/29fb25d624aecf0b075dea5c6029b2541474ddfe/smalivm/src/main/resources/props/android-27-emu/system/default.prop -------------------------------------------------------------------------------- /smalivm/src/main/resources/safe_methods.cfg: -------------------------------------------------------------------------------- 1 | // If a class cannot be white-listed, but some of the methods are safe, they can 2 | // be added here. They will be invoked via reflection using actual JVM objects. 3 | 4 | Ljava/lang/Class;->desiredAssertionStatus()Z 5 | Ljava/lang/Class;->getCanonicalName()Ljava/lang/String; 6 | Ljava/lang/Class;->getComponentType()Ljava/lang/Class; 7 | Ljava/lang/Class;->getDeclaredField(Ljava/lang/String;)Ljava/lang/reflect/Field; 8 | Ljava/lang/Class;->getDeclaredFields()[Ljava/lang/reflect/Field; 9 | Ljava/lang/Class;->getDeclaredMethod(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method; 10 | Ljava/lang/Class;->getDeclaredMethods()[Ljava/lang/reflect/Method; 11 | Ljava/lang/Class;->getField(Ljava/lang/String;)Ljava/lang/reflect/Field; 12 | Ljava/lang/Class;->getFields()[Ljava/lang/reflect/Field; 13 | Ljava/lang/Class;->getMethod(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method; 14 | Ljava/lang/Class;->getMethods()[Ljava/lang/reflect/Method; 15 | Ljava/lang/Class;->getModifiers()I 16 | Ljava/lang/Class;->getName()Ljava/lang/String; 17 | Ljava/lang/Class;->getPackage()Ljava/lang/Package; 18 | Ljava/lang/Class;->getSimpleName()Ljava/lang/String; 19 | Ljava/lang/Class;->getSuperclass()Ljava/lang/Class; 20 | Ljava/lang/Class;->isAnnotation()Z 21 | Ljava/lang/Class;->isAnonymousClass()Z 22 | Ljava/lang/Class;->isArray()Z 23 | Ljava/lang/Class;->isEnum()Z 24 | Ljava/lang/Class;->isInterface()Z 25 | Ljava/lang/Class;->isLocalClass()Z 26 | Ljava/lang/Class;->isMemberClass()Z 27 | Ljava/lang/Class;->isPrimitive()Z 28 | Ljava/lang/Class;->isSynthetic()Z 29 | Ljava/lang/Class;->toString()Ljava/lang/String; 30 | Ljava/lang/System;->arraycopy(Ljava/lang/Object;ILjava/lang/Object;II)V 31 | Ljava/lang/System;->currentTimeMillis()J 32 | Ljava/lang/System;->nanoTime()J 33 | Ljava/lang/Object;->getClass()Ljava/lang/Class; 34 | -------------------------------------------------------------------------------- /smalivm/src/main/resources/unsafe_methods.cfg: -------------------------------------------------------------------------------- 1 | // This file is useful when a class is white listed as safe but has a few methods which are unsafe. 2 | 3 | // It's unsafe to assume this method will always return the same value. 4 | Ljava/lang/Math;->random()D 5 | 6 | // No sleeping on the job please. 7 | Ljava/util/concurrent/TimeUnit;->sleep(J)V 8 | -------------------------------------------------------------------------------- /smalivm/src/test/java/org/cf/smalivm/VirtualMachineTest.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm; 2 | 3 | import static org.junit.jupiter.api.Assertions.fail; 4 | 5 | import org.junit.jupiter.api.BeforeEach; 6 | 7 | // These are not the tests you're looking for. *hand waving* 8 | public class VirtualMachineTest { 9 | 10 | @BeforeEach 11 | public void setUp() throws Exception { 12 | } 13 | 14 | public void test() { 15 | // test class static initialization 16 | // examine instruction graph 17 | // test some public methods 18 | fail("Not yet implemented"); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /smalivm/src/test/java/org/cf/smalivm/context/MethodStateTest.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.context; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | 5 | import org.cf.smalivm.VMTester; 6 | import org.junit.jupiter.api.Test; 7 | 8 | public class MethodStateTest { 9 | 10 | private static final String CLASS_NAME = "Lsimple_loop;"; 11 | 12 | @Test 13 | public void hasExpectedToString() { 14 | ExecutionGraph graph = VMTester.execute(CLASS_NAME, "simpleLoop()V"); 15 | 16 | ExecutionNode node = graph.getRoot(); 17 | MethodState state = node.getContext().getMethodState(); 18 | String expected = "params: 0, locals: 2\nv0: type=I, value=0"; 19 | 20 | assertEquals(expected, state.toString()); 21 | } 22 | 23 | @Test 24 | public void toStringHandlesNullRegisterValuesWhenPeekingAllRegisters() { 25 | ExecutionGraph graph = VMTester.execute(CLASS_NAME, "simpleLoop()V"); 26 | 27 | ExecutionNode node = graph.getRoot(); 28 | MethodState state = node.getContext().getMethodState(); 29 | String expected = "params: 0, locals: 2\nv0: type=I, value=0\nv1: null"; 30 | 31 | assertEquals(expected, state.toString(false)); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /smalivm/src/test/java/org/cf/smalivm/dex/ClassBuilderTest.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.dex; 2 | 3 | import java.io.IOException; 4 | import org.cf.smalivm.VMTester; 5 | import org.cf.smalivm.VirtualMachine; 6 | import org.cf.smalivm.exception.VirtualMachineException; 7 | import org.cf.smalivm.type.ClassManager; 8 | import org.cf.smalivm.type.ClassManagerFactory; 9 | import org.jf.dexlib2.iface.ClassDef; 10 | import org.junit.jupiter.api.BeforeEach; 11 | import org.junit.jupiter.api.Test; 12 | 13 | public class ClassBuilderTest { 14 | 15 | private static final String TEST_SMALI_PATH = VMTester.TEST_CLASS_PATH + "/class_builder"; 16 | 17 | private ClassBuilder classBuilder; 18 | private ClassManager classManager; 19 | 20 | @BeforeEach 21 | public void setUp() throws IOException { 22 | classManager = new ClassManagerFactory().build(TEST_SMALI_PATH); 23 | classBuilder = new ClassBuilder(classManager); 24 | } 25 | 26 | @Test 27 | public void canBuildSimpleClass() throws Exception { 28 | String className = "Lorg/cf/test/SimpleClass;"; 29 | ClassDef classDef = classManager.getVirtualClass(className).getClassDef(); 30 | classBuilder.build(classDef); 31 | } 32 | 33 | @Test 34 | public void canCallHashCodeOfDynamicallyGeneratedClass() throws VirtualMachineException { 35 | String className = "Lhash_code;"; 36 | String methodName = "createInstance()V"; 37 | VirtualMachine vm = VMTester.spawnVM(); 38 | vm.execute(className, methodName); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /smalivm/src/test/java/org/cf/smalivm/dex/FrameworkJarBuilderTest.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.dex; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | import java.net.URLClassLoader; 6 | import java.util.List; 7 | import org.cf.smalivm.configuration.Configuration; 8 | import org.cf.smalivm.configuration.ConfigurationLoader; 9 | import org.cf.util.ClassNameUtils; 10 | import org.junit.jupiter.api.Test; 11 | 12 | public class FrameworkJarBuilderTest { 13 | 14 | @Test 15 | public void frameworkClassesExistAndCanBeLoaded() throws IOException, ClassNotFoundException { 16 | List lines = ConfigurationLoader.load(Configuration.FRAMEWORK_CLASSES_PATH); 17 | URL jarURL = FrameworkJarBuilderTest.class.getResource(SmaliClassLoader.FRAMEWORK_STUBS_JAR); 18 | URLClassLoader jarLoader = new URLClassLoader(new URL[]{jarURL}); 19 | for (String line : lines) { 20 | String internalName = line.substring(0, line.indexOf(':')); 21 | if (internalName.startsWith("Ljava/") || internalName.startsWith("Lsun/security/")) { 22 | // Skip loading prohibited package names to avoid error. This isn't ideal, but 23 | // I can't think of an easy work around. This still loads a majority of classes. 24 | continue; 25 | } 26 | String sourceName = ClassNameUtils.internalToSource(internalName); 27 | 28 | // If the class was generated badly, this should error. 29 | jarLoader.loadClass(sourceName); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /smalivm/src/test/java/org/cf/smalivm/dex/SmaliParserTest.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.dex; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertTrue; 4 | 5 | import java.util.List; 6 | import org.cf.smalivm.VMTester; 7 | import org.jf.dexlib2.writer.builder.BuilderClassDef; 8 | import org.junit.jupiter.api.Test; 9 | 10 | public class SmaliParserTest { 11 | 12 | @Test 13 | public void canParseSmaliDirectory() throws Exception { 14 | List classDefs = SmaliParser.parse(VMTester.TEST_CLASS_PATH); 15 | assertTrue(classDefs.size() > 0); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /smalivm/src/test/java/org/cf/smalivm/opcode/MonitorEnterOpTest.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.opcode; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | 5 | import org.cf.smalivm.VMTester; 6 | import org.cf.smalivm.VirtualMachine; 7 | import org.cf.smalivm.context.ExecutionGraph; 8 | import org.cf.smalivm.context.ExecutionNode; 9 | import org.junit.jupiter.api.Test; 10 | 11 | public class MonitorEnterOpTest { 12 | private static final String CLASS_NAME = "Lmonitor_enter_test;"; 13 | 14 | @Test 15 | public void monitorEnterHasExpectedTostring() { 16 | String methodDescriptor = "monitorEnter()V"; 17 | VirtualMachine vm = VMTester.spawnVM(); 18 | ExecutionGraph graph = vm.spawnInstructionGraph(CLASS_NAME, methodDescriptor); 19 | ExecutionNode node = graph.getTemplateNode(1); 20 | assertEquals("monitor-enter r0", node.getOp().toString()); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /smalivm/src/test/java/org/cf/smalivm/opcode/MonitorExitOpTest.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.opcode; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | 5 | import org.cf.smalivm.VMTester; 6 | import org.cf.smalivm.VirtualMachine; 7 | import org.cf.smalivm.context.ExecutionGraph; 8 | import org.cf.smalivm.context.ExecutionNode; 9 | import org.junit.jupiter.api.Test; 10 | 11 | public class MonitorExitOpTest { 12 | private static final String CLASS_NAME = "Lmonitor_exit_test;"; 13 | 14 | @Test 15 | public void monitorEnterHasExpectedTostring() { 16 | String methodDescriptor = "monitorExit()V"; 17 | VirtualMachine vm = VMTester.spawnVM(); 18 | ExecutionGraph graph = vm.spawnInstructionGraph(CLASS_NAME, methodDescriptor); 19 | ExecutionNode node = graph.getTemplateNode(1); 20 | assertEquals("monitor-exit r0", node.getOp().toString()); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /smalivm/src/test/java/org/cf/smalivm/opcode/NewInstanceOpTest.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.opcode; 2 | 3 | import org.cf.smalivm.VMState; 4 | import org.cf.smalivm.VMTester; 5 | import org.cf.smalivm.VirtualMachine; 6 | import org.cf.smalivm.context.ExecutionGraph; 7 | import org.cf.smalivm.type.UninitializedInstance; 8 | import org.cf.smalivm.type.VirtualType; 9 | import org.junit.jupiter.api.BeforeEach; 10 | import org.junit.jupiter.api.Test; 11 | 12 | public class NewInstanceOpTest { 13 | 14 | private static final String CLASS_NAME = "Lnew_instance_test;"; 15 | 16 | private VMState expected; 17 | private VMState initial; 18 | private VirtualMachine vm; 19 | 20 | @Test 21 | public void canCreateLocalInstance() throws ClassNotFoundException { 22 | initial.setRegisters(0, 1, "I"); 23 | ExecutionGraph graph = VMTester.execute(vm, CLASS_NAME, "newLocalInstance()V", initial); 24 | 25 | VirtualType instanceType = vm.getClassManager().getVirtualType(CLASS_NAME); 26 | expected.setRegisters(0, new UninitializedInstance(instanceType), CLASS_NAME); 27 | VMTester.testState(graph, expected); 28 | } 29 | 30 | @Test 31 | public void canCreateNonLocalInstance() { 32 | initial.setRegisters(0, 1, "I"); 33 | ExecutionGraph graph = VMTester.execute(vm, CLASS_NAME, "newNonLocalInstance()V", initial); 34 | 35 | VirtualType instanceType = vm.getClassManager().getVirtualType("Ljava/lang/Integer;"); 36 | expected.setRegisters(0, new UninitializedInstance(instanceType), "Ljava/lang/Integer;"); 37 | VMTester.testState(graph, expected); 38 | } 39 | 40 | @BeforeEach 41 | public void setUp() { 42 | expected = new VMState(); 43 | initial = new VMState(); 44 | vm = VMTester.spawnVM(); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /smalivm/src/test/java/org/cf/smalivm/opcode/ThrowOpTest.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm.opcode; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | 5 | import org.cf.smalivm.VMState; 6 | import org.cf.smalivm.VMTester; 7 | import org.cf.smalivm.context.ExecutionGraph; 8 | import org.cf.smalivm.context.HeapItem; 9 | import org.cf.smalivm.context.MethodState; 10 | import org.cf.util.ClassNameUtils; 11 | import org.junit.jupiter.api.BeforeEach; 12 | import org.junit.jupiter.api.Test; 13 | 14 | public class ThrowOpTest { 15 | 16 | private static final String CLASS_NAME = "Lthrow_test;"; 17 | 18 | private VMState expected; 19 | private VMState initial; 20 | 21 | @BeforeEach 22 | public void setUp() { 23 | expected = new VMState(); 24 | initial = new VMState(); 25 | } 26 | 27 | @Test 28 | public void canThrowNullPointerException() { 29 | ExecutionGraph graph = VMTester.execute(CLASS_NAME, "throwNullPointerException()V", initial); 30 | 31 | Class exceptionClass = NullPointerException.class; 32 | HeapItem item = graph.getTerminatingRegisterConsensus(0); 33 | assertEquals(exceptionClass, item.getValue().getClass()); 34 | assertEquals(ClassNameUtils.toInternal(exceptionClass), item.getType()); 35 | 36 | HeapItem throwItem = graph.getTerminatingRegisterConsensus(MethodState.ThrowRegister); 37 | assertEquals(item, throwItem); 38 | 39 | VMTester.test(CLASS_NAME, "throwNullPointerException()V", expected); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/class_builder/CircularReference1.smali: -------------------------------------------------------------------------------- 1 | .class public Lorg/cf/test/CircularReference1; 2 | .super Ljava/lang/Object; 3 | 4 | .method public static test()Lorg/cf/test/CircularReference2; 5 | .locals 0 6 | 7 | return-void 8 | .end method 9 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/class_builder/CircularReference2.smali: -------------------------------------------------------------------------------- 1 | .class public Lorg/cf/test/CircularReference2; 2 | .super Ljava/lang/Object; 3 | 4 | .method public static test()Lorg/cf/test/CircularReference1; 5 | .locals 0 6 | 7 | return-void 8 | .end method 9 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/class_builder/ComplexClass.smali: -------------------------------------------------------------------------------- 1 | # ADD reference to super class as parameter 2 | .class public Lorg/cf/test/ComplexClass; 3 | .super Lorg/cf/test/SuperClass; 4 | 5 | .field public static someField:[Lorg/cf/test/ComplexClass$TestEnum; 6 | 7 | .method public static constructor ()V 8 | .locals 0 9 | return-void 10 | .end method 11 | 12 | # direct methods 13 | .method public constructor ()V 14 | .locals 0 15 | 16 | #@0 17 | .prologue 18 | .line 3 19 | invoke-direct {p0}, Lorg/cf/test/SuperClass;->()V 20 | 21 | #@3 22 | return-void 23 | .end method 24 | 25 | .method abstract public publicAbstractMethod()V 26 | .end method 27 | 28 | .method native protected nativeProtectedReturnsVoid()V 29 | .end method 30 | 31 | .method public static publicStaticWithIntParameter(I)V 32 | .locals 0 33 | 34 | return-void 35 | .end method 36 | 37 | .method public static publicStaticWhichTakesItself(Lorg/cf/test/ComplexClass;)V 38 | .locals 0 39 | 40 | return-void 41 | .end method 42 | 43 | .method private static privateStaticWithManyParameters(ZBCIJF[D[Ljava/lang/Object;)V 44 | .locals 0 45 | 46 | return-void 47 | .end method 48 | 49 | .method static packagePrivateWhichReturnsObject()Ljava/lang/Object; 50 | .locals 0 51 | const/4 v0, 0x0 52 | return-object v0 53 | .end method 54 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/class_builder/IllegalFieldModifiers.smali: -------------------------------------------------------------------------------- 1 | .class public interface abstract Lorg/cf/test/IllegalFieldModifiers; 2 | .super Ljava/lang/Object; 3 | 4 | .field private static final myInt:I 5 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/class_builder/NonExistentReference.smali: -------------------------------------------------------------------------------- 1 | .class public Lorg/cf/test/NonExistentReference; 2 | .super Ljava/lang/Object; 3 | 4 | .method public static test()Ldoes/not/exist; 5 | .locals 0 6 | 7 | return-void 8 | .end method 9 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/class_builder/OverloadedFields.smali: -------------------------------------------------------------------------------- 1 | .class Lorg/cf/test/OverloadedFields; 2 | .super Ljava/lang/Object; 3 | 4 | .field public static field1:Ljava/lang/Object; 5 | .field public static field1:I 6 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/class_builder/SelfReference.smali: -------------------------------------------------------------------------------- 1 | .class public Lorg/cf/test/SelfReference; 2 | .super Ljava/lang/Object; 3 | 4 | .field private INSTANCE:[Lorg/cf/test/SelfReference; 5 | 6 | .method public static takesItself(Lorg/cf/test/SelfReference;)V 7 | .locals 0 8 | 9 | return-void 10 | .end method 11 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/class_builder/SimpleClass.smali: -------------------------------------------------------------------------------- 1 | .class Lorg/cf/test/SimpleClass; 2 | .super Ljava/lang/Object; 3 | 4 | .method public static simpleLoop(ILjava/lang/Object;)V 5 | .locals 2 6 | 7 | const/4 v0, 0x0 8 | const/4 v1, 0x1 9 | const/4 v2, 0x2 10 | 11 | :begin 12 | if-gt v0, v2, :end 13 | 14 | nop 15 | add-int/2addr v0, v1 16 | goto :begin 17 | 18 | :end 19 | return-void 20 | .end method 21 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/class_builder/SimpleInterface.smali: -------------------------------------------------------------------------------- 1 | .class interface Lorg/cf/test/SimpleInterface; 2 | .super Ljava/lang/Object; 3 | 4 | 5 | # direct methods 6 | .method public constructor ()V 7 | .locals 0 8 | 9 | #@0 10 | .prologue 11 | .line 3 12 | invoke-direct {p0}, Ljava/lang/Object;->()V 13 | 14 | #@3 15 | return-void 16 | .end method 17 | 18 | .method public abstract interfaceMethod()V 19 | .end method 20 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/class_builder/SuperClass.smali: -------------------------------------------------------------------------------- 1 | .class Lorg/cf/test/SuperClass; 2 | .super Ljava/lang/Object; 3 | 4 | .method static constructor ()V 5 | .locals 0 6 | 7 | return-void 8 | .end method 9 | 10 | .method public constructor ()V 11 | .locals 0 12 | 13 | .prologue 14 | .line 3 15 | invoke-direct {p0}, Ljava/lang/Object;->()V 16 | 17 | return-void 18 | .end method 19 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/exceptions/CustomException.smali: -------------------------------------------------------------------------------- 1 | .class Lorg/cf/test/CustomException; 2 | .super Ljava/lang/Throwable; 3 | 4 | .method constructor ()V 5 | .locals 2 6 | 7 | .prologue 8 | .line 1 9 | move-object v0, p0 10 | 11 | .local v0, "this":Lorg/cf/test/CustomException; 12 | move-object v1, v0 13 | 14 | invoke-direct {v1}, Ljava/lang/Throwable;->()V 15 | 16 | return-void 17 | .end method 18 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/exceptions/ExceptionalCode.smali: -------------------------------------------------------------------------------- 1 | .class Lorg/cf/test/ExceptionalCode; 2 | .super Ljava/lang/Object; 3 | 4 | 5 | .method public static createAndThrowException()V 6 | .locals 1 7 | 8 | new-instance v0, Lorg/cf/test/CustomException; 9 | invoke-direct {v0}, Lorg/cf/test/CustomException;->()V 10 | 11 | throw v0 12 | 13 | return-void 14 | .end method 15 | 16 | 17 | .method public static callsExceptionalMethod()V 18 | .locals 1 19 | 20 | :try_start_1 21 | invoke-static {}, Lorg/cf/test/ExceptionalCode;->createAndThrowException()V 22 | :try_end_1 23 | .catch Lorg/cf/test/CustomException; {:try_start_1 .. :try_end_1} :catch_1 24 | .catch Ljava/lang/Exception; {:try_start_1 .. :try_end_1} :catch_2 25 | 26 | return-void 27 | 28 | :catch_1 29 | move-exception v0 30 | throw v0 31 | 32 | :catch_2 33 | move-exception v0 34 | throw v0 35 | .end method 36 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/field_get/DummyChildClass.smali: -------------------------------------------------------------------------------- 1 | .class public Lorg/cf/smalivm/unrelated/DummyChildClass; 2 | .super Lorg/cf/smalivm/DummyClass; 3 | 4 | .method public static dummyMethod()V 5 | .locals 0 6 | return-void 7 | .end method 8 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/field_get/DummyClass$DummyInnerClass.smali: -------------------------------------------------------------------------------- 1 | .class Lorg/cf/smalivm/DummyClass$DummyInnerClass; 2 | .super Ljava/lang/Object; 3 | .source "DummyClass.java" 4 | 5 | 6 | # annotations 7 | .annotation system Ldalvik/annotation/EnclosingClass; 8 | value = Lorg/cf/smalivm/DummyClass; 9 | .end annotation 10 | 11 | .annotation system Ldalvik/annotation/InnerClass; 12 | accessFlags = 0x2 13 | name = "DummyInnerClass" 14 | .end annotation 15 | 16 | 17 | # instance fields 18 | .field final synthetic this$0:Lorg/cf/smalivm/DummyClass; 19 | 20 | 21 | # direct methods 22 | .method private constructor (Lorg/cf/smalivm/DummyClass;)V 23 | .registers 2 24 | 25 | .prologue 26 | .line 19 27 | iput-object p1, p0, Lorg/cf/smalivm/DummyClass$DummyInnerClass;->this$0:Lorg/cf/smalivm/DummyClass; 28 | 29 | invoke-direct {p0}, Ljava/lang/Object;->()V 30 | 31 | return-void 32 | .end method 33 | 34 | .method public static dummyMethod()V 35 | .locals 0 36 | return-void 37 | .end method 38 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/field_get/DummyClass.java: -------------------------------------------------------------------------------- 1 | package org.cf.smalivm; 2 | 3 | public class DummyClass { 4 | 5 | public static final int publicStaticField = 0x10; 6 | protected static final int protectedStaticField = 0x11; 7 | private static final int privateStaticField = 0x12; 8 | 9 | public final int publicInstanceField; 10 | final int protectedInstanceField; 11 | private final int privateInstanceField; 12 | 13 | DummyClass() { 14 | publicInstanceField = 0x20; 15 | protectedInstanceField = 0x21; 16 | privateInstanceField = 0x22; 17 | } 18 | 19 | private class DummyInnerClass { 20 | 21 | } 22 | } 23 | 24 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/field_get/DummyClass.smali: -------------------------------------------------------------------------------- 1 | .class public Lorg/cf/smalivm/DummyClass; 2 | .super Ljava/lang/Object; 3 | .source "DummyClass.java" 4 | 5 | 6 | # annotations 7 | .annotation system Ldalvik/annotation/MemberClasses; 8 | value = { 9 | Lorg/cf/smalivm/DummyClass$DummyInnerClass; 10 | } 11 | .end annotation 12 | 13 | 14 | # static fields 15 | .field public static final publicStaticField:I = 0x10 16 | .field protected static final protectedStaticField:I = 0x11 17 | .field static final packagePrivateStaticField:I = 0x12 18 | .field private static final privateStaticField:I = 0x13 19 | 20 | 21 | # instance fields 22 | .field public final publicInstanceField:I 23 | .field protected final protectedInstanceField:I 24 | .field final packagePrivateInstanceField:I 25 | .field private final privateInstanceField:I 26 | 27 | 28 | # direct methods 29 | .method constructor ()V 30 | .registers 2 31 | 32 | .prologue 33 | .line 13 34 | invoke-direct {p0}, Ljava/lang/Object;->()V 35 | 36 | .line 14 37 | const/16 v0, 0x20 38 | 39 | iput v0, p0, Lorg/cf/smalivm/DummyClass;->publicInstanceField:I 40 | 41 | .line 15 42 | const/16 v0, 0x21 43 | 44 | iput v0, p0, Lorg/cf/smalivm/DummyClass;->protectedInstanceField:I 45 | 46 | .line 16 47 | const/16 v0, 0x22 48 | 49 | iput v0, p0, Lorg/cf/smalivm/DummyClass;->privateInstanceField:I 50 | 51 | .line 17 52 | return-void 53 | .end method 54 | 55 | .method public static dummyMethod()V 56 | .locals 0 57 | return-void 58 | .end method 59 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/field_get/SamePackageClass.smali: -------------------------------------------------------------------------------- 1 | .class public Lorg/cf/smalivm/SamePackageClass; 2 | .super Ljava/lang/Object; 3 | 4 | .method public static dummyMethod()V 5 | .locals 0 6 | return-void 7 | .end method 8 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/field_get/UnrelatedClass.smali: -------------------------------------------------------------------------------- 1 | .class public Lorg/cf/smalivm/unrelated/UnrelatedClass; 2 | .super Ljava/lang/Object; 3 | 4 | .method public static dummyMethod()V 5 | .locals 0 6 | return-void 7 | .end method 8 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/hash_code.smali: -------------------------------------------------------------------------------- 1 | .class Lhash_code; 2 | .super Ljava/lang/Object; 3 | 4 | # Seen in com/google/gson/JsonNull; 5 | .method public constructor ()V 6 | .locals 0 7 | invoke-direct {p0}, Ljava/lang/Object;->()V 8 | return-void 9 | .end method 10 | 11 | .method public hashCode()I 12 | .locals 1 13 | 14 | const-class v0, Lhash_code; 15 | invoke-virtual {v0}, Ljava/lang/Object;->hashCode()I 16 | move-result v0 17 | return v0 18 | .end method 19 | 20 | .method public static createInstance()V 21 | .locals 1 22 | new-instance v0, Lhash_code; 23 | invoke-virtual {v0}, Lhash_code;->()V 24 | return-void 25 | .end method -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/inheritance/child_class.smali: -------------------------------------------------------------------------------- 1 | .class public Lchild_class; 2 | .super Lparent_class; 3 | 4 | .field public static childField:I 5 | 6 | # direct methods 7 | .method public constructor ()V 8 | .locals 0 9 | 10 | #@0 11 | .prologue 12 | .line 3 13 | invoke-direct {p0}, Lparent_class;->()V 14 | 15 | #@3 16 | return-void 17 | .end method 18 | 19 | # virtual methods 20 | .method public someString()Ljava/lang/String; 21 | .locals 1 22 | 23 | #@0 24 | .prologue 25 | .line 7 26 | const-string v0, "child" 27 | 28 | #@2 29 | return-object v0 30 | .end method 31 | 32 | .method public abstractMethod()Ljava/lang/String; 33 | .locals 1 34 | 35 | const-string v0, "abstract?" 36 | 37 | return-object v0 38 | .end method 39 | 40 | .method public static callsAbstractMethod()Ljava/lang/String; 41 | .locals 1 42 | 43 | new-instance v0, Lchild_class; 44 | invoke-direct {v0}, Lchild_class;->()V 45 | 46 | invoke-virtual {v0}, Lparent_class;->abstractMethod()Ljava/lang/String; 47 | move-result-object v0 48 | 49 | return-object v0 50 | .end method 51 | 52 | .method public static callsParentMethod()Ljava/lang/String; 53 | .locals 1 54 | 55 | new-instance v0, Lchild_class; 56 | invoke-direct {v0}, Lchild_class;->()V 57 | 58 | invoke-virtual {v0}, Lchild_class;->parentMethod()Ljava/lang/String; 59 | move-result-object v0 60 | 61 | return-object v0 62 | .end method 63 | 64 | .method public static takesParameter(I)V 65 | .locals 0 66 | 67 | return-void 68 | .end method 69 | 70 | .method public static stubMethod()V 71 | .locals 0 72 | 73 | return-void 74 | .end method 75 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/inheritance/grandparent_class.smali: -------------------------------------------------------------------------------- 1 | .class Lgrandparent_class; 2 | .super Ljava/lang/Object; 3 | .implements Lgrandparent_interface; 4 | 5 | .field public static grandparentField:I 6 | .field public static intLiteral:I = 0x5 7 | 8 | .method public constructor ()V 9 | .locals 1 10 | 11 | const/4 v0, 0x4 12 | sput v0, Lgrandparent_class;->grandparentField:I 13 | 14 | return-void 15 | .end method 16 | 17 | .method public constructor ()V 18 | .locals 0 19 | 20 | #@0 21 | .prologue 22 | .line 3 23 | invoke-direct {p0}, Ljava/lang/Object;->()V 24 | 25 | #@3 26 | return-void 27 | .end method 28 | 29 | .method public interfaceMethod()V 30 | .locals 0 31 | 32 | #@0 33 | return-void 34 | .end method 35 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/inheritance/grandparent_interface.smali: -------------------------------------------------------------------------------- 1 | .class public interface abstract Lgrandparent_interface; 2 | .super Ljava/lang/Object; 3 | 4 | .method public abstract interfaceMethod()V 5 | .end method 6 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/inheritance/parent_class.smali: -------------------------------------------------------------------------------- 1 | .class Lparent_class; 2 | .super Lgrandparent_class; 3 | 4 | .field public static parentField:I 5 | 6 | 7 | .method public constructor ()V 8 | .locals 1 9 | 10 | const/4 v0, 0x3 11 | sput v0, Lparent_class;->parentField:I 12 | 13 | return-void 14 | .end method 15 | 16 | 17 | .method public constructor ()V 18 | .locals 0 19 | 20 | #@0 21 | .prologue 22 | .line 3 23 | invoke-direct {p0}, Ljava/lang/Object;->()V 24 | 25 | #@3 26 | return-void 27 | .end method 28 | 29 | 30 | .method public someString()Ljava/lang/String; 31 | .locals 1 32 | 33 | #@0 34 | .prologue 35 | .line 6 36 | const-string v0, "parent" 37 | 38 | #@2 39 | return-object v0 40 | .end method 41 | 42 | 43 | .method public abstract abstractMethod()Ljava/lang/String; 44 | .end method 45 | 46 | 47 | .method public parentMethod()Ljava/lang/String; 48 | .locals 1 49 | 50 | #@0 51 | .prologue 52 | .line 6 53 | const-string v0, "parentMethod" 54 | 55 | #@2 56 | return-object v0 57 | .end method 58 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/method_reflector_test.smali: -------------------------------------------------------------------------------- 1 | .class Lmethod_reflector_test; 2 | .super Ljava/lang/Object; 3 | 4 | 5 | .method public static initCharacterWithChar()V 6 | .locals 1 7 | 8 | # Can't set v0 to "new-instance" at Java level 9 | new-instance v0, Ljava/lang/Character; 10 | invoke-direct {v0, v1}, Ljava/lang/Character;->(C)V 11 | 12 | return-void 13 | .end method 14 | 15 | .method public static initUUIDWithTwoLongs()V 16 | .locals 5 17 | 18 | new-instance v0, Ljava/util/UUID; 19 | 20 | invoke-direct {v0, v1, v2, v3, v4}, Ljava/util/UUID;->(JJ)V 21 | 22 | return-void 23 | .end method 24 | 25 | .method public static intValueOfInteger()V 26 | .locals 1 27 | 28 | invoke-static {v0}, Ljava/lang/Integer;->intValue()I 29 | move-result v0 30 | 31 | return-void 32 | .end method 33 | 34 | .method public static initBooleanWithBoolean()V 35 | .locals 1 36 | 37 | new-instance v0, Ljava/lang/Boolean; 38 | invoke-direct {v0, v1}, Ljava/lang/Boolean;->(Z)V 39 | 40 | return-void 41 | .end method 42 | 43 | .method public static shortValueOfShort()V 44 | .locals 1 45 | 46 | invoke-static {v0}, Ljava/lang/Short;->valueOf(S)Ljava/lang/Short; 47 | move-result v0 48 | 49 | return-void 50 | .end method 51 | 52 | .method public static byteValueOfByte()V 53 | .locals 1 54 | 55 | invoke-static {v0}, Ljava/lang/Byte;->valueOf(B)Ljava/lang/Byte; 56 | move-result v0 57 | 58 | return-void 59 | .end method 60 | 61 | .method public static getClassMethod()V 62 | .locals 2 63 | 64 | invoke-virtual {v0, v1, v2}, Ljava/lang/Class;->getMethod(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method; 65 | move-result v0 66 | 67 | return-void 68 | .end method 69 | 70 | .method public static stringLength()V 71 | .locals 1 72 | 73 | :try_start_1 74 | invoke-virtual {v0}, Ljava/lang/String;->length()I 75 | :try_end_1 76 | .catch Ljava/lang/Exception; {:try_start_1 .. :try_end_1} :catch_1 77 | 78 | nop 79 | 80 | :catch_1 81 | return-void 82 | .end method 83 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/native_method_class.smali: -------------------------------------------------------------------------------- 1 | .class Lnative_method_class; 2 | .super Ljava/lang/Object; 3 | 4 | .method private native nativeMethod()V 5 | .end method -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/object_init/class_with_default_constructor.smali: -------------------------------------------------------------------------------- 1 | .class public Lclass_with_default_constructor; 2 | .super Ljava/lang/Object; 3 | 4 | .method public constructor ()V 5 | .locals 0 6 | 7 | invoke-direct {p0}, Ljava/lang/Object;->()V 8 | 9 | return-void 10 | .end method 11 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/object_init/class_without_default_constructor.smali: -------------------------------------------------------------------------------- 1 | .class public Lclass_without_default_constructor; 2 | .super Ljava/lang/Object; 3 | 4 | .method public constructor ([C)V 5 | .locals 0 6 | 7 | invoke-direct {p0}, Ljava/lang/Object;->()V 8 | 9 | return-void 10 | .end method 11 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/object_init/class_without_default_constructor_checks_null.smali: -------------------------------------------------------------------------------- 1 | .class public Lclass_without_default_constructor_checks_null; 2 | .super Ljava/lang/Object; 3 | 4 | .method public constructor ([C)V 5 | .locals 2 6 | 7 | invoke-direct {p0}, Ljava/lang/Object;->()V 8 | 9 | if-nez p1, :return 10 | 11 | new-instance v0, Ljava/lang/NullPointerException; 12 | const-string/jumbo v1, "You'll never reach the Dark Tower!" 13 | invoke-direct {v0, v1}, Ljava/lang/NullPointerException;->(Ljava/lang/String;)V 14 | throw v0 15 | 16 | :return 17 | return-void 18 | .end method 19 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/ops/aget_test.smali: -------------------------------------------------------------------------------- 1 | .class Laget_test; 2 | .super Ljava/lang/Object; 3 | 4 | .method public static getUninitializedInt()V 5 | .locals 2 6 | 7 | aget v0, v0, v1 8 | 9 | return-void 10 | .end method 11 | 12 | .method public static get()V 13 | .locals 2 14 | 15 | aget v0, v0, v1 16 | 17 | return-void 18 | .end method 19 | 20 | .method public static getWithCatch()V 21 | .locals 2 22 | 23 | :try_start_0 24 | aget v0, v0, v1 25 | :try_end_0 26 | .catch Ljava/lang/Exception; {:try_start_0 .. :try_end_0} :catch_0 27 | 28 | nop 29 | 30 | :return 31 | return-void 32 | 33 | :catch_0 34 | move-exception v0 35 | goto :return 36 | .end method 37 | 38 | .method public static getWide()V 39 | .locals 4 40 | 41 | aget-wide v0, v0, v1 42 | 43 | return-void 44 | .end method 45 | 46 | .method public static getObject()V 47 | .locals 3 48 | 49 | aget-object v0, v0, v1 50 | 51 | return-void 52 | .end method 53 | 54 | .method public static getBoolean()V 55 | .locals 3 56 | 57 | aget-boolean v0, v0, v1 58 | 59 | return-void 60 | .end method 61 | 62 | .method public static getByte()V 63 | .locals 3 64 | 65 | aget-byte v0, v0, v1 66 | 67 | return-void 68 | .end method 69 | 70 | .method public static getChar()V 71 | .locals 3 72 | 73 | aget-char v0, v0, v1 74 | 75 | return-void 76 | .end method 77 | 78 | .method public static getShort()V 79 | .locals 3 80 | 81 | aget-short v0, v0, v1 82 | 83 | return-void 84 | .end method 85 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/ops/aput_test.smali: -------------------------------------------------------------------------------- 1 | .class Laput_test; 2 | .super Ljava/lang/Object; 3 | 4 | .method public static put()V 5 | .locals 3 6 | 7 | aput v2, v0, v1 # v0[v1] = v2 8 | 9 | return-void 10 | .end method 11 | 12 | .method public static putWithCatch()V 13 | .locals 3 14 | 15 | :try_start_0 16 | aput v2, v0, v1 # v0[v1] = v2 17 | :try_end_0 18 | .catch Ljava/lang/Exception; {:try_start_0 .. :try_end_0} :catch_0 19 | 20 | nop 21 | 22 | :return 23 | return-void 24 | 25 | :catch_0 26 | move-exception v0 27 | goto :return 28 | 29 | return-void 30 | .end method 31 | 32 | .method public static putWide()V 33 | .locals 3 34 | 35 | aput-wide v2, v0, v1 36 | 37 | return-void 38 | .end method 39 | 40 | .method public static putObject()V 41 | .locals 3 42 | 43 | aput-object v2, v0, v1 44 | 45 | return-void 46 | .end method 47 | 48 | .method public static putObjects()V 49 | .locals 3 50 | 51 | aput-object v2, v0, v1 52 | aput-object v4, v0, v3 53 | 54 | return-void 55 | .end method 56 | 57 | .method public static putBoolean()V 58 | .locals 3 59 | 60 | aput-boolean v2, v0, v1 61 | 62 | return-void 63 | .end method 64 | 65 | .method public static putByte()V 66 | .locals 3 67 | 68 | aput-byte v2, v0, v1 69 | 70 | return-void 71 | .end method 72 | 73 | .method public static putChar()V 74 | .locals 3 75 | 76 | aput-char v2, v0, v1 77 | 78 | return-void 79 | .end method 80 | 81 | .method public static putShort()V 82 | .locals 3 83 | 84 | aput-short v2, v0, v1 85 | 86 | return-void 87 | .end method 88 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/ops/array_length_test.smali: -------------------------------------------------------------------------------- 1 | .class Larray_length_test; 2 | .super Ljava/lang/Object; 3 | 4 | .method public static getLength()V 5 | .locals 1 6 | 7 | array-length v0, v0 8 | 9 | return-void 10 | .end method 11 | 12 | .method public static getLengthWithCatch()V 13 | .locals 2 14 | 15 | :try_start_0 16 | array-length v0, v0 17 | :try_end_0 18 | .catch Ljava/lang/Exception; {:try_start_0 .. :try_end_0} :catch_0 19 | 20 | nop 21 | 22 | :return 23 | return-void 24 | 25 | :catch_0 26 | move-exception v0 27 | goto :return 28 | 29 | return-void 30 | .end method 31 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/ops/check_cast_test.smali: -------------------------------------------------------------------------------- 1 | .class Lcheck_cast_test; 2 | .super Ljava/lang/Object; 3 | 4 | .method public static castToObject()V 5 | .locals 1 6 | 7 | check-cast v0, Ljava/lang/Object; 8 | 9 | return-void 10 | .end method 11 | 12 | .method public static castToString()V 13 | .locals 1 14 | 15 | check-cast v0, Ljava/lang/String; 16 | 17 | return-void 18 | .end method 19 | 20 | .method public static castToStringWithCatch()V 21 | .locals 2 22 | 23 | :try_start_0 24 | check-cast v0, Ljava/lang/String; 25 | :try_end_0 26 | .catch Ljava/lang/Exception; {:try_start_0 .. :try_end_0} :catch_0 27 | 28 | nop 29 | 30 | :return 31 | return-void 32 | 33 | :catch_0 34 | move-exception v0 35 | goto :return 36 | 37 | return-void 38 | .end method 39 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/ops/class_with_static_init.smali: -------------------------------------------------------------------------------- 1 | .class Lclass_with_static_init; 2 | .super Ljava/lang/Object; 3 | 4 | .field public static string:Ljava/lang/String; 5 | 6 | .method public static constructor ()V 7 | .locals 1 8 | 9 | const-string v0, "Uhhh, about 11, sir." 10 | sput-object v0, Lclass_with_static_init;->string:Ljava/lang/String; 11 | 12 | return-void 13 | .end method 14 | 15 | .method public static getString()Ljava/lang/String; 16 | .locals 1 17 | 18 | sget-object v0, Lclass_with_static_init;->string:Ljava/lang/String; 19 | 20 | return v0 21 | .end method 22 | 23 | .method public static getStaticFieldFromInvokeStaticTestClass()Ljava/lang/String; 24 | .locals 1 25 | 26 | sget-object v0, Linvoke_static_test;->sometimes_initialized:Ljava/lang/String; 27 | 28 | return v0 29 | .end method 30 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/ops/cmp_test.smali: -------------------------------------------------------------------------------- 1 | .class Lcmp_test; 2 | .super Ljava/lang/Object; 3 | 4 | 5 | .method public static cmplFloat()V 6 | .locals 2 7 | 8 | cmpl-float v0, v0, v1 9 | 10 | return-void 11 | .end method 12 | 13 | .method public static cmpgFloat()V 14 | .locals 2 15 | 16 | cmpg-float v0, v0, v1 17 | 18 | return-void 19 | .end method 20 | 21 | .method public static cmplDouble()V 22 | .locals 4 23 | 24 | cmpl-double v0, v0, v2 25 | 26 | return-void 27 | .end method 28 | 29 | .method public static cmpgDouble()V 30 | .locals 4 31 | 32 | cmpg-double v0, v0, v2 33 | 34 | return-void 35 | .end method 36 | 37 | .method public static cmpLong()V 38 | .locals 4 39 | 40 | cmp-long v0, v0, v2 41 | 42 | return-void 43 | .end method 44 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/ops/filled_new_array_test.smali: -------------------------------------------------------------------------------- 1 | .class Lfilled_new_array_test; 2 | .super Ljava/lang/Object; 3 | 4 | .method public static filledNewArray()V 5 | .locals 3 6 | 7 | filled-new-array {v0, v1, v2}, [I 8 | 9 | return-void 10 | .end method 11 | 12 | .method public static filledNewArrayRange()V 13 | .locals 6 14 | 15 | filled-new-array/range {v0 .. v5}, [I 16 | 17 | return-void 18 | .end method 19 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/ops/iget_test.smali: -------------------------------------------------------------------------------- 1 | .class public Liget_test; 2 | .super Ljava/lang/Object; 3 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/ops/instanceof_test.smali: -------------------------------------------------------------------------------- 1 | .class Linstanceof_test; 2 | .super Ljava/lang/Object; 3 | 4 | .method public static instanceOfObject()V 5 | .locals 2 6 | 7 | instance-of v1, v0, Ljava/lang/Object; 8 | 9 | return-void 10 | .end method 11 | 12 | .method public static instanceOfString()V 13 | .locals 2 14 | 15 | instance-of v1, v0, Ljava/lang/String; 16 | 17 | return-void 18 | .end method 19 | 20 | .method public static instanceOfStringArray()V 21 | .locals 2 22 | 23 | instance-of v1, v0, [Ljava/lang/String; 24 | 25 | return-void 26 | .end method 27 | 28 | .method public static instanceOfIntArray()V 29 | .locals 2 30 | 31 | instance-of v1, v0, [I 32 | 33 | return-void 34 | .end method 35 | 36 | .method public static instanceOfObjectArray()V 37 | .locals 2 38 | 39 | instance-of v1, v0, [Ljava/lang/Object; 40 | 41 | return-void 42 | .end method 43 | 44 | .method public static instanceOf2DObjectArray()V 45 | .locals 2 46 | 47 | instance-of v1, v0, [[Ljava/lang/Object; 48 | 49 | return-void 50 | .end method 51 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/ops/invoke_direct_test.smali: -------------------------------------------------------------------------------- 1 | .class public Linvoke_direct_test; 2 | .super Ljava/lang/Object; 3 | 4 | .method public static callInitOfClassWithDefaultConstructor()V 5 | .locals 1 6 | 7 | invoke-direct {v0}, Lclass_with_default_constructor;->()V 8 | 9 | return-void 10 | .end method 11 | 12 | .method public static callInitOfClassWithoutDefaultConstructor()V 13 | .locals 2 14 | 15 | invoke-direct {v0, v1}, Lclass_without_default_constructor;->([C)V 16 | 17 | return-void 18 | .end method 19 | 20 | .method public static callInitOfClassWithoutDefaultConstructorWhichChecksForNullArgument()V 21 | .locals 2 22 | 23 | invoke-direct {v0, v1}, Lclass_without_default_constructor_checks_null;->([C)V 24 | 25 | return-void 26 | .end method 27 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/ops/invoke_emulated_test.smali: -------------------------------------------------------------------------------- 1 | .class Linvoke_emulated_test; 2 | .super Ljava/lang/Object; 3 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/ops/invoke_reflected_test.smali: -------------------------------------------------------------------------------- 1 | .class Linvoke_reflected_test; 2 | .super Ljava/lang/Object; 3 | 4 | .method public static invokeLongValueOf()V 5 | .locals 2 6 | 7 | invoke-static {v0}, Ljava/lang/Long;->valueOf(J)Ljava/lang/Long; 8 | 9 | return-void 10 | .end method 11 | 12 | .method public static invokeBooleanValueOf()V 13 | .locals 1 14 | 15 | invoke-static {v0}, Ljava/lang/Boolean;->valueOf(Z)Ljava/lang/Boolean; 16 | 17 | return-void 18 | .end method 19 | 20 | .method public static invokeStringBuilderAppendWithLong()V 21 | .locals 3 22 | 23 | invoke-virtual {v0, v1, v2}, Ljava/lang/StringBuilder;->append(J)Ljava/lang/StringBuilder; 24 | 25 | return-void 26 | .end method 27 | 28 | .method public static initStringWithByteArray()V 29 | .locals 2 30 | 31 | invoke-virtual {v0, v1}, Ljava/lang/String;->([B)V 32 | 33 | return-void 34 | .end method 35 | 36 | .method public static addToListAndGet()V 37 | .locals 3 38 | 39 | invoke-interface {v0, v1}, Ljava/util/List;->add(Ljava/lang/Object;)Z 40 | invoke-interface {v0, v2}, Ljava/util/List;->get(I)Ljava/lang/Object; 41 | move-result-object v0 42 | 43 | return-void 44 | .end method 45 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/ops/iput_test.smali: -------------------------------------------------------------------------------- 1 | .class public Liput_test; 2 | .super Ljava/lang/Object; 3 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/ops/monitor_enter_test.smali: -------------------------------------------------------------------------------- 1 | .class Lmonitor_enter_test; 2 | .super Ljava/lang/Object; 3 | 4 | .method public static monitorEnter()V 5 | .locals 1 6 | const/4 v0, 0x0 7 | monitor-enter v0 8 | return-void 9 | .end method 10 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/ops/monitor_exit_test.smali: -------------------------------------------------------------------------------- 1 | .class Lmonitor_exit_test; 2 | .super Ljava/lang/Object; 3 | 4 | .method public static monitorExit()V 5 | .locals 1 6 | const/4 v0, 0x0 7 | monitor-exit v0 8 | return-void 9 | .end method 10 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/ops/move_test.smali: -------------------------------------------------------------------------------- 1 | .class Lmove_test; 2 | .super Ljava/lang/Object; 3 | 4 | .method public static moveRegisterPrimitive()V 5 | .locals 2 6 | 7 | move v1, v0 8 | 9 | return-void 10 | .end method 11 | 12 | .method public static moveRegisterObject()V 13 | .locals 2 14 | 15 | move-object v1, v0 16 | 17 | return-void 18 | .end method 19 | 20 | .method public static moveResult()V 21 | .locals 1 22 | 23 | move-result v0 24 | 25 | return-void 26 | .end method 27 | 28 | .method public static moveException()V 29 | .locals 1 30 | 31 | move-exception v0 32 | 33 | return-void 34 | .end method 35 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/ops/new_array_test.smali: -------------------------------------------------------------------------------- 1 | .class Lnew_array_test; 2 | .super Ljava/lang/Object; 3 | 4 | .method public static createIntegerArray()V 5 | .locals 1 6 | 7 | new-array v0, v0, [I 8 | 9 | return-void 10 | .end method 11 | 12 | .method public static create2DIntegerArray()V 13 | .locals 1 14 | 15 | new-array v0, v0, [[I 16 | 17 | return-void 18 | .end method 19 | 20 | .method public static createLocalInstanceArray()V 21 | .locals 1 22 | 23 | new-array v0, v0, [Lnew_array_test; 24 | 25 | return-void 26 | .end method 27 | 28 | .method public static create2DLocalInstanceArray()V 29 | .locals 1 30 | 31 | new-array v0, v0, [[Lnew_array_test; 32 | 33 | return-void 34 | .end method 35 | 36 | .method public static createNonExistentArrayClass()V 37 | .locals 1 38 | 39 | :try_start_0 40 | new-array v0, v0, [Ldoes/not/exist; 41 | :try_end_0 42 | .catch Ljava/lang/Exception; {:try_start_0 .. :try_end_0} :catch_0 43 | 44 | nop 45 | 46 | :return 47 | return-void 48 | 49 | :catch_0 50 | move-exception v0 51 | goto :return 52 | 53 | return-void 54 | .end method 55 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/ops/new_instance_test.smali: -------------------------------------------------------------------------------- 1 | .class Lnew_instance_test; 2 | .super Ljava/lang/Object; 3 | 4 | .method public static newLocalInstance()V 5 | .locals 1 6 | 7 | new-instance v0, Lnew_instance_test; 8 | 9 | return-void 10 | .end method 11 | 12 | .method public static newNonLocalInstance()V 13 | .locals 1 14 | 15 | new-instance v0, Ljava/lang/Integer; 16 | 17 | return-void 18 | .end method 19 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/ops/sput_test.smali: -------------------------------------------------------------------------------- 1 | .class public Lsput_test; 2 | .super Ljava/lang/Object; 3 | 4 | .field public static myInt:I 5 | .field public static myLong:J 6 | .field public static myString:Ljava/lang/String; 7 | .field public static myBoolean:Z 8 | .field public static myByte:B 9 | .field public static myChar:C 10 | .field public static myShort:S 11 | 12 | .method public static putStaticInt()V 13 | .locals 1 14 | sput v0, Lsput_test;->myInt:I 15 | return-void 16 | .end method 17 | 18 | .method public static putStaticWide()V 19 | .locals 1 20 | sput-wide v0, Lsput_test;->myLong:J 21 | return-void 22 | .end method 23 | 24 | .method public static putStaticObject()V 25 | .locals 1 26 | sput-object v0, Lsput_test;->myString:Ljava/lang/String; 27 | return-void 28 | .end method 29 | 30 | .method public static putStaticBoolean()V 31 | .locals 1 32 | sput-boolean v0, Lsput_test;->myBoolean:Z 33 | return-void 34 | .end method 35 | 36 | .method public static putStaticByte()V 37 | .locals 1 38 | sput-byte v0, Lsput_test;->myByte:B 39 | return-void 40 | .end method 41 | 42 | .method public static putStaticChar()V 43 | .locals 1 44 | sput-char v0, Lsput_test;->myChar:C 45 | return-void 46 | .end method 47 | 48 | .method public static putStaticShort()V 49 | .locals 1 50 | sput-short v0, Lsput_test;->myShort:S 51 | return-void 52 | .end method 53 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/ops/swich_test.smali: -------------------------------------------------------------------------------- 1 | .class public Lswitch_test; 2 | .super Ljava/lang/Object; 3 | 4 | .method public static packedSwitch()V 5 | .locals 1 6 | 7 | # If switch is first op, it masks if offset addresses are calculated correctly. 8 | # @0 9 | goto :switch 10 | 11 | :switch 12 | # @1 13 | packed-switch v0, :pswitch_data_0 14 | 15 | # @4 16 | return-void 17 | 18 | :pswitch_0 19 | # @5 20 | return-void 21 | 22 | :pswitch_1 23 | # @6 24 | return-void 25 | 26 | :pswitch_2 27 | # @7 28 | return-void 29 | 30 | # @8 31 | nop # for alignment 32 | 33 | :pswitch_data_0 34 | .packed-switch 0x1 35 | :pswitch_0 36 | :pswitch_1 37 | :pswitch_2 38 | .end packed-switch 39 | .end method 40 | 41 | .method public static sparseSwitch()V 42 | .locals 1 43 | 44 | # If switch is first op, it masks if offset addresses are calculated correctly. 45 | goto :switch # @0 46 | 47 | :switch 48 | sparse-switch v0, :sswitch_data_0 # @1 49 | 50 | return-void # @4 51 | 52 | :sswitch_0 53 | return-void # @5 54 | 55 | :sswitch_1 56 | return-void # @6 57 | 58 | nop # @7, for alignment 59 | 60 | :sswitch_data_0 61 | .sparse-switch # @8 62 | 0x1 -> :sswitch_0 63 | 0x2 -> :sswitch_1 64 | .end sparse-switch 65 | .end method 66 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/ops/throw_test.smali: -------------------------------------------------------------------------------- 1 | .class Lthrow_test; 2 | .super Ljava/lang/Object; 3 | 4 | .method public static throwNullPointerException()V 5 | .locals 1 6 | 7 | :try_start_1 8 | # Throw a null pointer exception 9 | const/4 v0, 0x0 10 | invoke-virtual {v0}, Ljava/lang/String;->length()I 11 | :try_end_1 12 | .catch Ljava/lang/Exception; {:try_start_1 .. :try_end_1} :catch_1 13 | 14 | return-void 15 | 16 | :catch_1 17 | move-exception v0 18 | throw v0 19 | .end method 20 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/side_effects/no_side_effect.smali: -------------------------------------------------------------------------------- 1 | .class Lno_side_effect; 2 | .super Ljava/lang/Object; 3 | 4 | .method public static constructor ()V 5 | .locals 2 6 | 7 | const/4 v0, 0x5 8 | const-string v0, "nothing to see here" 9 | 10 | # Gradle or something is proxy'ing out:Ljava/io/PrintStream; and it can't be cloned. 11 | # This makes the cloner unhappy, and causes failures. 12 | # Tests run fine in Eclipse. 13 | #sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream; 14 | #const-string v1, "hello,world!" 15 | #invoke-virtual {v0, v1}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V 16 | 17 | return-void 18 | .end method 19 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/side_effects/strong_side_effect.smali: -------------------------------------------------------------------------------- 1 | .class Lstrong_side_effect; 2 | .super Ljava/lang/Object; 3 | 4 | # Writes malbytes to secretFile. Any IO is strong side effect. 5 | .method public static constructor ()V 6 | .locals 7 7 | .annotation system Ldalvik/annotation/Throws; 8 | value = { 9 | Ljava/lang/Exception; 10 | } 11 | .end annotation 12 | 13 | .prologue 14 | .line 16 15 | new-instance v2, Ljava/io/FileOutputStream; 16 | move-object v6, v2 17 | move-object v2, v6 18 | move-object v3, v6 19 | 20 | const-string v4, "secretFile" 21 | invoke-direct {v3, v4}, Ljava/io/FileOutputStream;->(Ljava/lang/String;)V 22 | move-object v0, v2 23 | 24 | .line 17 25 | const/4 v2, 0x3 26 | new-array v2, v2, [B 27 | fill-array-data v2, :array_0 28 | move-object v1, v2 29 | 30 | .line 18 31 | move-object v2, v0 32 | move-object v3, v1 33 | invoke-virtual {v2, v3}, Ljava/io/OutputStream;->write([B)V 34 | 35 | .line 19 36 | return-void 37 | 38 | .line 17 39 | :array_0 40 | .array-data 1 41 | 0x1t 42 | 0x2t 43 | 0x3t 44 | .end array-data 45 | .end method 46 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/side_effects/weak_side_effect.smali: -------------------------------------------------------------------------------- 1 | .class Lweak_side_effect; 2 | .super Ljava/lang/Object; 3 | 4 | .field public static stringAccessedByThread:Ljava/lang/String; 5 | 6 | # Modifying data not local to method side-effect, but this is not direct side-effect. 7 | # Would need clever thread to watch this value. 8 | .method public static constructor ()V 9 | .locals 1 10 | 11 | const-string v0, "nothing to see here" 12 | sput-object v0, Lweak_side_effect;->stringAccessedByThread:Ljava/lang/String; 13 | 14 | return-void 15 | .end method 16 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/simple_loop.smali: -------------------------------------------------------------------------------- 1 | .class Lsimple_loop; 2 | .super Ljava/lang/Object; 3 | 4 | .method public static simpleLoop()V 5 | .locals 2 6 | 7 | const/4 v0, 0x0 8 | const/4 v1, 0x1 9 | const/4 v2, 0x2 10 | 11 | :begin 12 | if-gt v0, v2, :end 13 | 14 | nop 15 | add-int/2addr v0, v1 16 | goto :begin 17 | 18 | :end 19 | return-void 20 | .end method 21 | -------------------------------------------------------------------------------- /smalivm/src/test/resources/smali/static_fields_test.smali: -------------------------------------------------------------------------------- 1 | .class public Lstatic_fields_test; 2 | .super Ljava/lang/Object; 3 | 4 | .field private static alwaysZero:I 5 | .field private static testInt1:I 6 | .field private static testInt2:I 7 | 8 | .field private static myList:Ljava/util/List; 9 | 10 | .method public static ()V 11 | .locals 1 12 | sget v0, Lstatic_fields_test;->alwaysZero:I 13 | sput v0, Lstatic_fields_test;->testInt1:I 14 | 15 | const/4 v0, 0x1 16 | sput v0, Lstatic_fields_test;->testInt2:I 17 | 18 | return-void 19 | .end method 20 | 21 | .method public constructor ()V 22 | .locals 0 23 | invoke-direct {p0}, Ljava/lang/Object;->()V 24 | return-void 25 | .end method 26 | 27 | .method public static stubMethod()V 28 | .locals 0 29 | return-void 30 | .end method 31 | 32 | .method public static stubMethod2()V 33 | .locals 0 34 | invoke-static {}, Lstatic_fields_test;->stubMethod()V 35 | return-void 36 | .end method 37 | 38 | .method static callMethodWhichCallsAnotherMethodThenGetsField()V 39 | .locals 2 40 | 41 | new-instance v0, Ljava/util/ArrayList; 42 | sput-object v0, Lstatic_fields_test;->myList:Ljava/util/List; 43 | 44 | const/4 v1, 0x5 45 | invoke-direct {v0, v1}, Ljava/util/ArrayList;->(I)V 46 | 47 | invoke-static {}, Lstatic_fields_test;->stubMethod2()V 48 | const-string v1, "added item!" 49 | invoke-virtual {v0, v1}, Ljava/util/ArrayList;->add(Ljava/lang/Object;)Z 50 | 51 | sget-object v0, Lstatic_fields_test;->myList:Ljava/util/List; 52 | 53 | return-void 54 | .end method 55 | 56 | .method static callMethodThenGetField()V 57 | .locals 2 58 | 59 | new-instance v0, Ljava/util/ArrayList; 60 | sput-object v0, Lstatic_fields_test;->myList:Ljava/util/List; 61 | 62 | const/4 v1, 0x5 63 | invoke-direct {v0, v1}, Ljava/util/ArrayList;->(I)V 64 | 65 | invoke-static {}, Lstatic_fields_test;->stubMethod()V 66 | const-string v1, "added item!" 67 | invoke-virtual {v0, v1}, Ljava/util/ArrayList;->add(Ljava/lang/Object;)Z 68 | 69 | sget-object v0, Lstatic_fields_test;->myList:Ljava/util/List; 70 | 71 | return-void 72 | .end method 73 | --------------------------------------------------------------------------------