├── .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 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
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 | [](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 |
4 |
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 |
10 |
--------------------------------------------------------------------------------
/simplify/ObfuscatedApp/app/src/main/res/values-v21/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/simplify/ObfuscatedApp/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/simplify/ObfuscatedApp/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/simplify/ObfuscatedApp/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Obfuscated
5 | Hello world!
6 | Settings
7 |
8 |
9 |
--------------------------------------------------------------------------------
/simplify/ObfuscatedApp/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
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 extends Throwable> exceptionClass) {
21 | return build(op, exceptionClass, null);
22 | }
23 |
24 | public Throwable build(Op op, Class extends Throwable> exceptionClass, String message) {
25 | try {
26 | Constructor extends Throwable> 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 extends Enum>) 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 |
--------------------------------------------------------------------------------