mirror of
https://github.com/revanced/Apktool.git
synced 2024-08-15 03:40:34 +02:00
Merge pull request #1059 from iBotPeaches/smali-submodule
Remove smali project in favor of smali submodule
This commit is contained in:
commit
e7c1bcefe8
3
.gitignore
vendored
3
.gitignore
vendored
@ -20,3 +20,6 @@ bin/
|
||||
*.iml
|
||||
.idea/*
|
||||
/out
|
||||
|
||||
# gradle/smali-patches patch smali/ into brut.apktool.smali/
|
||||
brut.apktool.smali/
|
||||
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
[submodule "smali"]
|
||||
path = smali
|
||||
url = git@github.com:JesusFreke/smali.git
|
17
.travis.yml
17
.travis.yml
@ -1,6 +1,8 @@
|
||||
env:
|
||||
- TERM=dumb
|
||||
language: java
|
||||
git:
|
||||
submodules: false
|
||||
jdk:
|
||||
- openjdk7
|
||||
- oraclejdk7
|
||||
@ -8,18 +10,15 @@ jdk:
|
||||
os:
|
||||
- linux
|
||||
before_install:
|
||||
- git config --global user.email "travis@connortumbleson.com"
|
||||
- git config --global user.name "Travis CI Bot"
|
||||
- sudo apt-get update -qq
|
||||
- sudo apt-get install -qq libstdc++6:i386 lib32z1 expect
|
||||
script: ./scripts/travis-ci/run-tests.sh
|
||||
- sed -i 's/git@github.com:/https:\/\/github.com\//' .gitmodules
|
||||
- git submodule update --init --recursive
|
||||
install: ./gradlew applyPatches
|
||||
script: ./gradlew build fatJar proguard
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- stable
|
||||
notifications:
|
||||
irc:
|
||||
channels:
|
||||
- "chat.freenode.net#apktool"
|
||||
on_success: change
|
||||
on_failure: always
|
||||
template:
|
||||
- "%{repository_name} (%{commit}) : %{duration} - %{message}"
|
||||
|
6
brut.apktool.smali/.gitignore
vendored
6
brut.apktool.smali/.gitignore
vendored
@ -1,6 +0,0 @@
|
||||
/baksmali/target/
|
||||
/dexlib/target/
|
||||
/maven-smali-plugin/target/
|
||||
/smali/target/
|
||||
/util/target/
|
||||
*~
|
@ -1,49 +0,0 @@
|
||||
The majority of smali/baksmali is written and copyrighted by me (Ben Gruver)
|
||||
and released under the following license:
|
||||
|
||||
*******************************************************************************
|
||||
Copyright (c) 2010 Ben Gruver (JesusFreke)
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************
|
||||
|
||||
|
||||
Various portions of the code are taken from the Android Open Source Project,
|
||||
and are used in accordance with the following license:
|
||||
|
||||
*******************************************************************************
|
||||
Copyright (C) 2007 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*******************************************************************************
|
@ -1,84 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath depends.proguard_gradle
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile project(':brut.apktool.smali:util')
|
||||
compile project(':brut.apktool.smali:dexlib2')
|
||||
compile depends.commons_cli
|
||||
compile depends.guava
|
||||
|
||||
testCompile depends.junit
|
||||
testCompile project(':brut.apktool.smali:smali')
|
||||
}
|
||||
|
||||
processResources.inputs.property('version', version)
|
||||
processResources.expand('version': version)
|
||||
|
||||
// build a jar containing all dependencies
|
||||
task fatJar (type: Jar) {
|
||||
from sourceSets.main.output
|
||||
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
|
||||
|
||||
manifest {
|
||||
attributes('Main-Class': 'org.jf.baksmali.main')
|
||||
}
|
||||
}
|
||||
|
||||
tasks.getByPath('build').dependsOn(fatJar)
|
||||
|
||||
task proguard(type: proguard.gradle.ProGuardTask, dependsOn: fatJar) {
|
||||
def outFile = fatJar.destinationDir.getPath() + '/' + fatJar.baseName + '-' + fatJar.version + '-small' + '.' + fatJar.extension
|
||||
|
||||
injars fatJar.archivePath
|
||||
outjars outFile
|
||||
|
||||
libraryjars "${System.properties['java.home']}/lib/rt.jar"
|
||||
|
||||
dontobfuscate
|
||||
dontoptimize
|
||||
|
||||
keep 'public class org.jf.baksmali.main { public static void main(java.lang.String[]); }'
|
||||
keepclassmembers 'enum * { public static **[] values(); public static ** valueOf(java.lang.String); }'
|
||||
|
||||
dontwarn 'com.google.common.**'
|
||||
dontnote 'com.google.common.**'
|
||||
}
|
||||
|
||||
tasks.getByPath(':release').dependsOn(proguard)
|
@ -1,69 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 Ben Gruver (JesusFreke)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali.Adaptors;
|
||||
|
||||
import org.jf.baksmali.Adaptors.EncodedValue.AnnotationEncodedValueAdaptor;
|
||||
import org.jf.dexlib2.AnnotationVisibility;
|
||||
import org.jf.dexlib2.iface.Annotation;
|
||||
import org.jf.util.IndentingWriter;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
|
||||
public class AnnotationFormatter {
|
||||
|
||||
public static void writeTo(@Nonnull IndentingWriter writer,
|
||||
@Nonnull Collection<? extends Annotation> annotations,
|
||||
@Nullable String containingClass) throws IOException {
|
||||
boolean first = true;
|
||||
for (Annotation annotation: annotations) {
|
||||
if (!first) {
|
||||
writer.write('\n');
|
||||
}
|
||||
first = false;
|
||||
|
||||
writeTo(writer, annotation, containingClass);
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeTo(@Nonnull IndentingWriter writer, @Nonnull Annotation annotation,
|
||||
@Nullable String containingClass) throws IOException {
|
||||
writer.write(".annotation ");
|
||||
writer.write(AnnotationVisibility.getVisibility(annotation.getVisibility()));
|
||||
writer.write(' ');
|
||||
writer.write(annotation.getType());
|
||||
writer.write('\n');
|
||||
|
||||
AnnotationEncodedValueAdaptor.writeElementsTo(writer, annotation.getElements(), containingClass);
|
||||
|
||||
writer.write(".end annotation\n");
|
||||
}
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 Ben Gruver (JesusFreke)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali.Adaptors;
|
||||
|
||||
import org.jf.util.IndentingWriter;
|
||||
|
||||
//a "spacer" between instructions
|
||||
public class BlankMethodItem extends MethodItem {
|
||||
public BlankMethodItem(int codeAddress) {
|
||||
super(codeAddress);
|
||||
}
|
||||
|
||||
public double getSortOrder() {
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
public boolean writeTo(IndentingWriter writer) {
|
||||
//we didn't technically print something, but returning true indicates that a newline should be printed
|
||||
//after this method item, which is the intended functionality
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,97 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 Ben Gruver (JesusFreke)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali.Adaptors;
|
||||
|
||||
import org.jf.baksmali.baksmaliOptions;
|
||||
import org.jf.util.IndentingWriter;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.IOException;
|
||||
|
||||
public class CatchMethodItem extends MethodItem {
|
||||
private final String exceptionType;
|
||||
|
||||
private final LabelMethodItem tryStartLabel;
|
||||
private final LabelMethodItem tryEndLabel;
|
||||
private final LabelMethodItem handlerLabel;
|
||||
|
||||
public CatchMethodItem(@Nonnull baksmaliOptions options, @Nonnull MethodDefinition.LabelCache labelCache,
|
||||
int codeAddress, @Nullable String exceptionType, int startAddress, int endAddress,
|
||||
int handlerAddress) {
|
||||
super(codeAddress);
|
||||
this.exceptionType = exceptionType;
|
||||
|
||||
tryStartLabel = labelCache.internLabel(new LabelMethodItem(options, startAddress, "try_start_"));
|
||||
|
||||
//use the address from the last covered instruction, but make the label
|
||||
//name refer to the address of the next instruction
|
||||
tryEndLabel = labelCache.internLabel(new EndTryLabelMethodItem(options, codeAddress, endAddress));
|
||||
|
||||
if (exceptionType == null) {
|
||||
handlerLabel = labelCache.internLabel(new LabelMethodItem(options, handlerAddress, "catchall_"));
|
||||
} else {
|
||||
handlerLabel = labelCache.internLabel(new LabelMethodItem(options, handlerAddress, "catch_"));
|
||||
}
|
||||
}
|
||||
|
||||
public LabelMethodItem getTryStartLabel() {
|
||||
return tryStartLabel;
|
||||
}
|
||||
|
||||
public LabelMethodItem getTryEndLabel() {
|
||||
return tryEndLabel;
|
||||
}
|
||||
|
||||
public LabelMethodItem getHandlerLabel() {
|
||||
return handlerLabel;
|
||||
}
|
||||
|
||||
public double getSortOrder() {
|
||||
//sort after instruction and end_try label
|
||||
return 102;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean writeTo(IndentingWriter writer) throws IOException {
|
||||
if (exceptionType == null) {
|
||||
writer.write(".catchall");
|
||||
} else {
|
||||
writer.write(".catch ");
|
||||
writer.write(exceptionType);
|
||||
}
|
||||
writer.write(" {");
|
||||
tryStartLabel.writeTo(writer);
|
||||
writer.write(" .. ");
|
||||
tryEndLabel.writeTo(writer);
|
||||
writer.write("} ");
|
||||
handlerLabel.writeTo(writer);
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,331 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 Ben Gruver (JesusFreke)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali.Adaptors;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import org.jf.baksmali.baksmaliOptions;
|
||||
import org.jf.dexlib2.AccessFlags;
|
||||
import org.jf.dexlib2.dexbacked.DexBackedClassDef;
|
||||
import org.jf.dexlib2.dexbacked.DexBackedDexFile.InvalidItemIndex;
|
||||
import org.jf.dexlib2.iface.*;
|
||||
import org.jf.dexlib2.iface.instruction.Instruction;
|
||||
import org.jf.dexlib2.iface.instruction.formats.Instruction21c;
|
||||
import org.jf.dexlib2.iface.reference.FieldReference;
|
||||
import org.jf.dexlib2.util.ReferenceUtil;
|
||||
import org.jf.util.IndentingWriter;
|
||||
import org.jf.util.StringUtils;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
public class ClassDefinition {
|
||||
@Nonnull public final baksmaliOptions options;
|
||||
@Nonnull public final ClassDef classDef;
|
||||
@Nonnull private final HashSet<String> fieldsSetInStaticConstructor;
|
||||
|
||||
protected boolean validationErrors;
|
||||
|
||||
public ClassDefinition(@Nonnull baksmaliOptions options, @Nonnull ClassDef classDef) {
|
||||
this.options = options;
|
||||
this.classDef = classDef;
|
||||
fieldsSetInStaticConstructor = findFieldsSetInStaticConstructor();
|
||||
}
|
||||
|
||||
public boolean hadValidationErrors() {
|
||||
return validationErrors;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private HashSet<String> findFieldsSetInStaticConstructor() {
|
||||
HashSet<String> fieldsSetInStaticConstructor = new HashSet<String>();
|
||||
|
||||
for (Method method: classDef.getDirectMethods()) {
|
||||
if (method.getName().equals("<clinit>")) {
|
||||
MethodImplementation impl = method.getImplementation();
|
||||
if (impl != null) {
|
||||
for (Instruction instruction: impl.getInstructions()) {
|
||||
switch (instruction.getOpcode()) {
|
||||
case SPUT:
|
||||
case SPUT_BOOLEAN:
|
||||
case SPUT_BYTE:
|
||||
case SPUT_CHAR:
|
||||
case SPUT_OBJECT:
|
||||
case SPUT_SHORT:
|
||||
case SPUT_WIDE: {
|
||||
Instruction21c ins = (Instruction21c)instruction;
|
||||
FieldReference fieldRef = null;
|
||||
try {
|
||||
fieldRef = (FieldReference)ins.getReference();
|
||||
} catch (InvalidItemIndex ex) {
|
||||
// just ignore it for now. We'll deal with it later, when processing the instructions
|
||||
// themselves
|
||||
}
|
||||
if (fieldRef != null &&
|
||||
fieldRef.getDefiningClass().equals((classDef.getType()))) {
|
||||
fieldsSetInStaticConstructor.add(ReferenceUtil.getShortFieldDescriptor(fieldRef));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return fieldsSetInStaticConstructor;
|
||||
}
|
||||
|
||||
public void writeTo(IndentingWriter writer) throws IOException {
|
||||
writeClass(writer);
|
||||
writeSuper(writer);
|
||||
writeSourceFile(writer);
|
||||
writeInterfaces(writer);
|
||||
writeAnnotations(writer);
|
||||
Set<String> staticFields = writeStaticFields(writer);
|
||||
writeInstanceFields(writer, staticFields);
|
||||
Set<String> directMethods = writeDirectMethods(writer);
|
||||
writeVirtualMethods(writer, directMethods);
|
||||
}
|
||||
|
||||
private void writeClass(IndentingWriter writer) throws IOException {
|
||||
writer.write(".class ");
|
||||
writeAccessFlags(writer);
|
||||
writer.write(classDef.getType());
|
||||
writer.write('\n');
|
||||
}
|
||||
|
||||
private void writeAccessFlags(IndentingWriter writer) throws IOException {
|
||||
for (AccessFlags accessFlag: AccessFlags.getAccessFlagsForClass(classDef.getAccessFlags())) {
|
||||
writer.write(accessFlag.toString());
|
||||
writer.write(' ');
|
||||
}
|
||||
}
|
||||
|
||||
private void writeSuper(IndentingWriter writer) throws IOException {
|
||||
String superClass = classDef.getSuperclass();
|
||||
if (superClass != null) {
|
||||
writer.write(".super ");
|
||||
writer.write(superClass);
|
||||
writer.write('\n');
|
||||
}
|
||||
}
|
||||
|
||||
private void writeSourceFile(IndentingWriter writer) throws IOException {
|
||||
String sourceFile = classDef.getSourceFile();
|
||||
if (sourceFile != null) {
|
||||
writer.write(".source \"");
|
||||
StringUtils.writeEscapedString(writer, sourceFile);
|
||||
writer.write("\"\n");
|
||||
}
|
||||
}
|
||||
|
||||
private void writeInterfaces(IndentingWriter writer) throws IOException {
|
||||
List<String> interfaces = classDef.getInterfaces();
|
||||
|
||||
if (interfaces.size() != 0) {
|
||||
writer.write('\n');
|
||||
writer.write("# interfaces\n");
|
||||
for (String interfaceName: interfaces) {
|
||||
writer.write(".implements ");
|
||||
writer.write(interfaceName);
|
||||
writer.write('\n');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void writeAnnotations(IndentingWriter writer) throws IOException {
|
||||
Collection<? extends Annotation> classAnnotations = classDef.getAnnotations();
|
||||
if (classAnnotations.size() != 0) {
|
||||
writer.write("\n\n");
|
||||
writer.write("# annotations\n");
|
||||
|
||||
String containingClass = null;
|
||||
if (options.useImplicitReferences) {
|
||||
containingClass = classDef.getType();
|
||||
}
|
||||
|
||||
AnnotationFormatter.writeTo(writer, classAnnotations, containingClass);
|
||||
}
|
||||
}
|
||||
|
||||
private Set<String> writeStaticFields(IndentingWriter writer) throws IOException {
|
||||
boolean wroteHeader = false;
|
||||
Set<String> writtenFields = new HashSet<String>();
|
||||
|
||||
Iterable<? extends Field> staticFields;
|
||||
if (classDef instanceof DexBackedClassDef) {
|
||||
staticFields = ((DexBackedClassDef)classDef).getStaticFields(false);
|
||||
} else {
|
||||
staticFields = classDef.getStaticFields();
|
||||
}
|
||||
|
||||
for (Field field: staticFields) {
|
||||
if (!wroteHeader) {
|
||||
writer.write("\n\n");
|
||||
writer.write("# static fields");
|
||||
wroteHeader = true;
|
||||
}
|
||||
writer.write('\n');
|
||||
|
||||
boolean setInStaticConstructor;
|
||||
IndentingWriter fieldWriter = writer;
|
||||
String fieldString = ReferenceUtil.getShortFieldDescriptor(field);
|
||||
if (!writtenFields.add(fieldString)) {
|
||||
writer.write("# duplicate field ignored\n");
|
||||
fieldWriter = new CommentingIndentingWriter(writer);
|
||||
System.err.println(String.format("Ignoring duplicate field: %s->%s", classDef.getType(), fieldString));
|
||||
setInStaticConstructor = false;
|
||||
} else {
|
||||
setInStaticConstructor = fieldsSetInStaticConstructor.contains(fieldString);
|
||||
}
|
||||
FieldDefinition.writeTo(options, fieldWriter, field, setInStaticConstructor);
|
||||
}
|
||||
return writtenFields;
|
||||
}
|
||||
|
||||
private void writeInstanceFields(IndentingWriter writer, Set<String> staticFields) throws IOException {
|
||||
boolean wroteHeader = false;
|
||||
Set<String> writtenFields = new HashSet<String>();
|
||||
|
||||
Iterable<? extends Field> instanceFields;
|
||||
if (classDef instanceof DexBackedClassDef) {
|
||||
instanceFields = ((DexBackedClassDef)classDef).getInstanceFields(false);
|
||||
} else {
|
||||
instanceFields = classDef.getInstanceFields();
|
||||
}
|
||||
|
||||
for (Field field: instanceFields) {
|
||||
if (!wroteHeader) {
|
||||
writer.write("\n\n");
|
||||
writer.write("# instance fields");
|
||||
wroteHeader = true;
|
||||
}
|
||||
writer.write('\n');
|
||||
|
||||
IndentingWriter fieldWriter = writer;
|
||||
String fieldString = ReferenceUtil.getShortFieldDescriptor(field);
|
||||
if (!writtenFields.add(fieldString)) {
|
||||
writer.write("# duplicate field ignored\n");
|
||||
fieldWriter = new CommentingIndentingWriter(writer);
|
||||
System.err.println(String.format("Ignoring duplicate field: %s->%s", classDef.getType(), fieldString));
|
||||
} else if (staticFields.contains(fieldString)) {
|
||||
System.err.println(String.format("Duplicate static+instance field found: %s->%s",
|
||||
classDef.getType(), fieldString));
|
||||
System.err.println("You will need to rename one of these fields, including all references.");
|
||||
|
||||
writer.write("# There is both a static and instance field with this signature.\n" +
|
||||
"# You will need to rename one of these fields, including all references.\n");
|
||||
}
|
||||
FieldDefinition.writeTo(options, fieldWriter, field, false);
|
||||
}
|
||||
}
|
||||
|
||||
private Set<String> writeDirectMethods(IndentingWriter writer) throws IOException {
|
||||
boolean wroteHeader = false;
|
||||
Set<String> writtenMethods = new HashSet<String>();
|
||||
|
||||
Iterable<? extends Method> directMethods;
|
||||
if (classDef instanceof DexBackedClassDef) {
|
||||
directMethods = ((DexBackedClassDef)classDef).getDirectMethods(false);
|
||||
} else {
|
||||
directMethods = classDef.getDirectMethods();
|
||||
}
|
||||
|
||||
for (Method method: directMethods) {
|
||||
if (!wroteHeader) {
|
||||
writer.write("\n\n");
|
||||
writer.write("# direct methods");
|
||||
wroteHeader = true;
|
||||
}
|
||||
writer.write('\n');
|
||||
|
||||
// TODO: check for method validation errors
|
||||
String methodString = ReferenceUtil.getMethodDescriptor(method, true);
|
||||
|
||||
IndentingWriter methodWriter = writer;
|
||||
if (!writtenMethods.add(methodString)) {
|
||||
writer.write("# duplicate method ignored\n");
|
||||
methodWriter = new CommentingIndentingWriter(writer);
|
||||
}
|
||||
|
||||
MethodImplementation methodImpl = method.getImplementation();
|
||||
if (methodImpl == null) {
|
||||
MethodDefinition.writeEmptyMethodTo(methodWriter, method, options);
|
||||
} else {
|
||||
MethodDefinition methodDefinition = new MethodDefinition(this, method, methodImpl);
|
||||
methodDefinition.writeTo(methodWriter);
|
||||
}
|
||||
}
|
||||
return writtenMethods;
|
||||
}
|
||||
|
||||
private void writeVirtualMethods(IndentingWriter writer, Set<String> directMethods) throws IOException {
|
||||
boolean wroteHeader = false;
|
||||
Set<String> writtenMethods = new HashSet<String>();
|
||||
|
||||
Iterable<? extends Method> virtualMethods;
|
||||
if (classDef instanceof DexBackedClassDef) {
|
||||
virtualMethods = ((DexBackedClassDef)classDef).getVirtualMethods(false);
|
||||
} else {
|
||||
virtualMethods = classDef.getVirtualMethods();
|
||||
}
|
||||
|
||||
for (Method method: virtualMethods) {
|
||||
if (!wroteHeader) {
|
||||
writer.write("\n\n");
|
||||
writer.write("# virtual methods");
|
||||
wroteHeader = true;
|
||||
}
|
||||
writer.write('\n');
|
||||
|
||||
// TODO: check for method validation errors
|
||||
String methodString = ReferenceUtil.getMethodDescriptor(method, true);
|
||||
|
||||
IndentingWriter methodWriter = writer;
|
||||
if (!writtenMethods.add(methodString)) {
|
||||
writer.write("# duplicate method ignored\n");
|
||||
methodWriter = new CommentingIndentingWriter(writer);
|
||||
} else if (directMethods.contains(methodString)) {
|
||||
writer.write("# There is both a direct and virtual method with this signature.\n" +
|
||||
"# You will need to rename one of these methods, including all references.\n");
|
||||
System.err.println(String.format("Duplicate direct+virtual method found: %s->%s",
|
||||
classDef.getType(), methodString));
|
||||
System.err.println("You will need to rename one of these methods, including all references.");
|
||||
}
|
||||
|
||||
MethodImplementation methodImpl = method.getImplementation();
|
||||
if (methodImpl == null) {
|
||||
MethodDefinition.writeEmptyMethodTo(methodWriter, method, options);
|
||||
} else {
|
||||
MethodDefinition methodDefinition = new MethodDefinition(this, method, methodImpl);
|
||||
methodDefinition.writeTo(methodWriter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 Ben Gruver (JesusFreke)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali.Adaptors;
|
||||
|
||||
import org.jf.util.IndentingWriter;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class CommentMethodItem extends MethodItem {
|
||||
//private final StringTemplate template;
|
||||
private final String comment;
|
||||
private final double sortOrder;
|
||||
|
||||
public CommentMethodItem(String comment, int codeAddress, double sortOrder) {
|
||||
super(codeAddress);
|
||||
this.comment = comment;
|
||||
this.sortOrder = sortOrder;
|
||||
}
|
||||
|
||||
public double getSortOrder() {
|
||||
return sortOrder;
|
||||
}
|
||||
|
||||
public boolean writeTo(IndentingWriter writer) throws IOException {
|
||||
writer.write('#');
|
||||
writer.write(comment);
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 Ben Gruver (JesusFreke)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali.Adaptors;
|
||||
|
||||
import org.jf.util.IndentingWriter;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class CommentedOutMethodItem extends MethodItem {
|
||||
private final MethodItem commentedOutMethodItem;
|
||||
|
||||
public CommentedOutMethodItem(MethodItem commentedOutMethodItem) {
|
||||
super(commentedOutMethodItem.getCodeAddress());
|
||||
this.commentedOutMethodItem = commentedOutMethodItem;
|
||||
}
|
||||
|
||||
public double getSortOrder() {
|
||||
return commentedOutMethodItem.getSortOrder() + .001;
|
||||
}
|
||||
|
||||
public boolean writeTo(IndentingWriter writer) throws IOException {
|
||||
writer.write('#');
|
||||
commentedOutMethodItem.writeTo(writer);
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali.Adaptors;
|
||||
|
||||
import org.jf.util.IndentingWriter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
|
||||
public class CommentingIndentingWriter extends IndentingWriter {
|
||||
public CommentingIndentingWriter(Writer writer) {
|
||||
super(writer);
|
||||
}
|
||||
|
||||
@Override protected void writeIndent() throws IOException {
|
||||
writer.write("# ");
|
||||
super.writeIndent();
|
||||
}
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali.Adaptors.Debug;
|
||||
|
||||
import org.jf.util.IndentingWriter;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class BeginEpilogueMethodItem extends DebugMethodItem {
|
||||
public BeginEpilogueMethodItem(int codeAddress, int sortOrder) {
|
||||
super(codeAddress, sortOrder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean writeTo(IndentingWriter writer) throws IOException {
|
||||
writer.write(".prologue");
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali.Adaptors.Debug;
|
||||
|
||||
import org.jf.baksmali.Adaptors.MethodItem;
|
||||
import org.jf.baksmali.Adaptors.RegisterFormatter;
|
||||
import org.jf.dexlib2.DebugItemType;
|
||||
import org.jf.dexlib2.iface.debug.*;
|
||||
import org.jf.util.ExceptionWithContext;
|
||||
|
||||
public abstract class DebugMethodItem extends MethodItem {
|
||||
private final int sortOrder;
|
||||
|
||||
protected DebugMethodItem(int codeAddress, int sortOrder) {
|
||||
super(codeAddress);
|
||||
this.sortOrder = sortOrder;
|
||||
}
|
||||
|
||||
@Override public double getSortOrder() { return sortOrder; }
|
||||
|
||||
public static DebugMethodItem build(RegisterFormatter registerFormatter, DebugItem debugItem) {
|
||||
int codeAddress = debugItem.getCodeAddress();
|
||||
switch (debugItem.getDebugItemType()) {
|
||||
case DebugItemType.START_LOCAL:
|
||||
return new StartLocalMethodItem(codeAddress, -1, registerFormatter, (StartLocal)debugItem);
|
||||
case DebugItemType.END_LOCAL:
|
||||
return new EndLocalMethodItem(codeAddress, -1, registerFormatter, (EndLocal)debugItem);
|
||||
case DebugItemType.RESTART_LOCAL:
|
||||
return new RestartLocalMethodItem(codeAddress, -1, registerFormatter, (RestartLocal)debugItem);
|
||||
case DebugItemType.EPILOGUE_BEGIN:
|
||||
return new BeginEpilogueMethodItem(codeAddress, -4);
|
||||
case DebugItemType.PROLOGUE_END:
|
||||
return new EndPrologueMethodItem(codeAddress, -4);
|
||||
case DebugItemType.SET_SOURCE_FILE:
|
||||
return new SetSourceFileMethodItem(codeAddress, -3, (SetSourceFile)debugItem);
|
||||
case DebugItemType.LINE_NUMBER:
|
||||
return new LineNumberMethodItem(codeAddress, -2, (LineNumber)debugItem);
|
||||
default:
|
||||
throw new ExceptionWithContext("Invalid debug item type: %d", debugItem.getDebugItemType());
|
||||
}
|
||||
}
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali.Adaptors.Debug;
|
||||
|
||||
import org.jf.baksmali.Adaptors.RegisterFormatter;
|
||||
import org.jf.dexlib2.iface.debug.EndLocal;
|
||||
import org.jf.util.IndentingWriter;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.io.IOException;
|
||||
|
||||
public class EndLocalMethodItem extends DebugMethodItem {
|
||||
@Nonnull private final EndLocal endLocal;
|
||||
@Nonnull private final RegisterFormatter registerFormatter;
|
||||
|
||||
public EndLocalMethodItem(int codeAddress, int sortOrder, @Nonnull RegisterFormatter registerFormatter,
|
||||
@Nonnull EndLocal endLocal) {
|
||||
super(codeAddress, sortOrder);
|
||||
this.endLocal = endLocal;
|
||||
this.registerFormatter = registerFormatter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean writeTo(IndentingWriter writer) throws IOException {
|
||||
writer.write(".end local ");
|
||||
registerFormatter.writeTo(writer, endLocal.getRegister());
|
||||
|
||||
String name = endLocal.getName();
|
||||
String type = endLocal.getType();
|
||||
String signature = endLocal.getSignature();
|
||||
if (name != null || type != null || signature != null) {
|
||||
writer.write(" # ");
|
||||
LocalFormatter.writeLocal(writer, name, type, signature);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali.Adaptors.Debug;
|
||||
|
||||
import org.jf.util.IndentingWriter;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class EndPrologueMethodItem extends DebugMethodItem {
|
||||
public EndPrologueMethodItem(int codeAddress, int sortOrder) {
|
||||
super(codeAddress, sortOrder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean writeTo(IndentingWriter writer) throws IOException {
|
||||
writer.write(".prologue");
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali.Adaptors.Debug;
|
||||
|
||||
import org.jf.dexlib2.iface.debug.LineNumber;
|
||||
import org.jf.util.IndentingWriter;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.io.IOException;
|
||||
|
||||
public class LineNumberMethodItem extends DebugMethodItem {
|
||||
private final int lineNumber;
|
||||
|
||||
public LineNumberMethodItem(int codeAddress, int sortOrder, @Nonnull LineNumber lineNumber) {
|
||||
super(codeAddress, sortOrder);
|
||||
this.lineNumber = lineNumber.getLineNumber();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean writeTo(IndentingWriter writer) throws IOException {
|
||||
writer.write(".line ");
|
||||
writer.printUnsignedIntAsDec(lineNumber);
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali.Adaptors.Debug;
|
||||
|
||||
import org.jf.baksmali.Adaptors.ReferenceFormatter;
|
||||
import org.jf.util.IndentingWriter;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.IOException;
|
||||
|
||||
public class LocalFormatter {
|
||||
/**
|
||||
* Writes out the given local info
|
||||
*
|
||||
* The written string will be something like:
|
||||
*
|
||||
* "localVar":Ljava/lang/String;, "SomeSignature"
|
||||
* "localVar":Ljava/lang/String;
|
||||
* "localVar":V, "SomeSignature"
|
||||
* null:Ljava/lang/String;, "SomeSignature"
|
||||
* null:V, "SomeSignature"
|
||||
*
|
||||
* One of name, type or signature must be non-null
|
||||
*/
|
||||
public static void writeLocal(@Nonnull IndentingWriter writer, @Nullable String name, @Nullable String type,
|
||||
@Nullable String signature) throws IOException {
|
||||
if (name != null) {
|
||||
ReferenceFormatter.writeStringReference(writer, name);
|
||||
} else {
|
||||
writer.write("null");
|
||||
}
|
||||
writer.write(':');
|
||||
if (type != null) {
|
||||
writer.write(type);
|
||||
} else {
|
||||
writer.write("V");
|
||||
}
|
||||
if (signature != null) {
|
||||
writer.write(", ");
|
||||
ReferenceFormatter.writeStringReference(writer, signature);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali.Adaptors.Debug;
|
||||
|
||||
import org.jf.baksmali.Adaptors.RegisterFormatter;
|
||||
import org.jf.dexlib2.iface.debug.RestartLocal;
|
||||
import org.jf.util.IndentingWriter;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.io.IOException;
|
||||
|
||||
public class RestartLocalMethodItem extends DebugMethodItem {
|
||||
@Nonnull private final RestartLocal restartLocal;
|
||||
@Nonnull private final RegisterFormatter registerFormatter;
|
||||
|
||||
public RestartLocalMethodItem(int codeAddress, int sortOrder, @Nonnull RegisterFormatter registerFormatter,
|
||||
@Nonnull RestartLocal restartLocal) {
|
||||
super(codeAddress, sortOrder);
|
||||
this.restartLocal = restartLocal;
|
||||
this.registerFormatter = registerFormatter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean writeTo(IndentingWriter writer) throws IOException {
|
||||
writer.write(".restart local ");
|
||||
registerFormatter.writeTo(writer, restartLocal.getRegister());
|
||||
|
||||
String name = restartLocal.getName();
|
||||
String type = restartLocal.getType();
|
||||
String signature = restartLocal.getSignature();
|
||||
if (name != null || type != null || signature != null) {
|
||||
writer.write(" # ");
|
||||
LocalFormatter.writeLocal(writer, name, type, signature);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali.Adaptors.Debug;
|
||||
|
||||
import org.jf.dexlib2.iface.debug.SetSourceFile;
|
||||
import org.jf.util.IndentingWriter;
|
||||
import org.jf.util.StringUtils;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.IOException;
|
||||
|
||||
public class SetSourceFileMethodItem extends DebugMethodItem {
|
||||
@Nullable private final String sourceFile;
|
||||
|
||||
public SetSourceFileMethodItem(int codeAddress, int sortOrder, @Nonnull SetSourceFile setSourceFile) {
|
||||
super(codeAddress, sortOrder);
|
||||
this.sourceFile = setSourceFile.getSourceFile();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean writeTo(IndentingWriter writer) throws IOException {
|
||||
writer.write(".source");
|
||||
|
||||
if (sourceFile != null) {
|
||||
writer.write(" \"");
|
||||
StringUtils.writeEscapedString(writer, sourceFile);
|
||||
writer.write('"');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali.Adaptors.Debug;
|
||||
|
||||
import org.jf.baksmali.Adaptors.RegisterFormatter;
|
||||
import org.jf.dexlib2.iface.debug.StartLocal;
|
||||
import org.jf.util.IndentingWriter;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.io.IOException;
|
||||
|
||||
public class StartLocalMethodItem extends DebugMethodItem {
|
||||
@Nonnull private final StartLocal startLocal;
|
||||
@Nonnull private final RegisterFormatter registerFormatter;
|
||||
|
||||
public StartLocalMethodItem(int codeAddress, int sortOrder, @Nonnull RegisterFormatter registerFormatter,
|
||||
@Nonnull StartLocal startLocal) {
|
||||
super(codeAddress, sortOrder);
|
||||
this.startLocal = startLocal;
|
||||
this.registerFormatter = registerFormatter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean writeTo(IndentingWriter writer) throws IOException {
|
||||
writer.write(".local ");
|
||||
registerFormatter.writeTo(writer, startLocal.getRegister());
|
||||
|
||||
String name = startLocal.getName();
|
||||
String type = startLocal.getType();
|
||||
String signature = startLocal.getSignature();
|
||||
|
||||
if (name != null || type != null || signature != null) {
|
||||
writer.write(", ");
|
||||
LocalFormatter.writeLocal(writer, name, type, signature);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 Ben Gruver (JesusFreke)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali.Adaptors.EncodedValue;
|
||||
|
||||
import org.jf.dexlib2.iface.AnnotationElement;
|
||||
import org.jf.dexlib2.iface.value.AnnotationEncodedValue;
|
||||
import org.jf.util.IndentingWriter;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
|
||||
public abstract class AnnotationEncodedValueAdaptor {
|
||||
|
||||
public static void writeTo(@Nonnull IndentingWriter writer,
|
||||
@Nonnull AnnotationEncodedValue annotationEncodedValue,
|
||||
@Nullable String containingClass) throws IOException {
|
||||
writer.write(".subannotation ");
|
||||
writer.write(annotationEncodedValue.getType());
|
||||
writer.write('\n');
|
||||
|
||||
writeElementsTo(writer, annotationEncodedValue.getElements(), containingClass);
|
||||
writer.write(".end subannotation");
|
||||
}
|
||||
|
||||
public static void writeElementsTo(@Nonnull IndentingWriter writer,
|
||||
@Nonnull Collection<? extends AnnotationElement> annotationElements,
|
||||
@Nullable String containingClass) throws IOException {
|
||||
writer.indent(4);
|
||||
for (AnnotationElement annotationElement: annotationElements) {
|
||||
writer.write(annotationElement.getName());
|
||||
writer.write(" = ");
|
||||
EncodedValueAdaptor.writeTo(writer, annotationElement.getValue(), containingClass);
|
||||
writer.write('\n');
|
||||
}
|
||||
writer.deindent(4);
|
||||
}
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 Ben Gruver (JesusFreke)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali.Adaptors.EncodedValue;
|
||||
|
||||
import org.jf.dexlib2.iface.value.ArrayEncodedValue;
|
||||
import org.jf.dexlib2.iface.value.EncodedValue;
|
||||
import org.jf.util.IndentingWriter;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
|
||||
public class ArrayEncodedValueAdaptor {
|
||||
public static void writeTo(@Nonnull IndentingWriter writer,
|
||||
@Nonnull ArrayEncodedValue arrayEncodedValue,
|
||||
@Nullable String containingClass) throws IOException {
|
||||
writer.write('{');
|
||||
Collection<? extends EncodedValue> values = arrayEncodedValue.getValue();
|
||||
if (values.size() == 0) {
|
||||
writer.write('}');
|
||||
return;
|
||||
}
|
||||
|
||||
writer.write('\n');
|
||||
writer.indent(4);
|
||||
boolean first = true;
|
||||
for (EncodedValue encodedValue: values) {
|
||||
if (!first) {
|
||||
writer.write(",\n");
|
||||
}
|
||||
first = false;
|
||||
|
||||
EncodedValueAdaptor.writeTo(writer, encodedValue, containingClass);
|
||||
}
|
||||
writer.deindent(4);
|
||||
writer.write("\n}");
|
||||
}
|
||||
}
|
@ -1,112 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 Ben Gruver (JesusFreke)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali.Adaptors.EncodedValue;
|
||||
|
||||
import org.jf.baksmali.Adaptors.ReferenceFormatter;
|
||||
import org.jf.baksmali.Renderers.*;
|
||||
import org.jf.dexlib2.ValueType;
|
||||
import org.jf.dexlib2.iface.value.*;
|
||||
import org.jf.dexlib2.util.ReferenceUtil;
|
||||
import org.jf.util.IndentingWriter;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.IOException;
|
||||
|
||||
public abstract class EncodedValueAdaptor {
|
||||
public static void writeTo(@Nonnull IndentingWriter writer, @Nonnull EncodedValue encodedValue,
|
||||
@Nullable String containingClass)
|
||||
throws IOException {
|
||||
switch (encodedValue.getValueType()) {
|
||||
case ValueType.ANNOTATION:
|
||||
AnnotationEncodedValueAdaptor.writeTo(writer, (AnnotationEncodedValue)encodedValue, containingClass);
|
||||
return;
|
||||
case ValueType.ARRAY:
|
||||
ArrayEncodedValueAdaptor.writeTo(writer, (ArrayEncodedValue)encodedValue, containingClass);
|
||||
return;
|
||||
case ValueType.BOOLEAN:
|
||||
BooleanRenderer.writeTo(writer, ((BooleanEncodedValue)encodedValue).getValue());
|
||||
return;
|
||||
case ValueType.BYTE:
|
||||
ByteRenderer.writeTo(writer, ((ByteEncodedValue)encodedValue).getValue());
|
||||
return;
|
||||
case ValueType.CHAR:
|
||||
CharRenderer.writeTo(writer, ((CharEncodedValue)encodedValue).getValue());
|
||||
return;
|
||||
case ValueType.DOUBLE:
|
||||
DoubleRenderer.writeTo(writer, ((DoubleEncodedValue)encodedValue).getValue());
|
||||
return;
|
||||
case ValueType.ENUM:
|
||||
EnumEncodedValue enumEncodedValue = (EnumEncodedValue)encodedValue;
|
||||
boolean useImplicitReference = false;
|
||||
if (enumEncodedValue.getValue().getDefiningClass().equals(containingClass)) {
|
||||
useImplicitReference = true;
|
||||
}
|
||||
writer.write(".enum ");
|
||||
ReferenceUtil.writeFieldDescriptor(writer, enumEncodedValue.getValue(), useImplicitReference);
|
||||
return;
|
||||
case ValueType.FIELD:
|
||||
FieldEncodedValue fieldEncodedValue = (FieldEncodedValue)encodedValue;
|
||||
useImplicitReference = false;
|
||||
if (fieldEncodedValue.getValue().getDefiningClass().equals(containingClass)) {
|
||||
useImplicitReference = true;
|
||||
}
|
||||
ReferenceUtil.writeFieldDescriptor(writer, fieldEncodedValue.getValue(), useImplicitReference);
|
||||
return;
|
||||
case ValueType.FLOAT:
|
||||
FloatRenderer.writeTo(writer, ((FloatEncodedValue)encodedValue).getValue());
|
||||
return;
|
||||
case ValueType.INT:
|
||||
IntegerRenderer.writeTo(writer, ((IntEncodedValue)encodedValue).getValue());
|
||||
return;
|
||||
case ValueType.LONG:
|
||||
LongRenderer.writeTo(writer, ((LongEncodedValue)encodedValue).getValue());
|
||||
return;
|
||||
case ValueType.METHOD:
|
||||
MethodEncodedValue methodEncodedValue = (MethodEncodedValue)encodedValue;
|
||||
useImplicitReference = false;
|
||||
if (methodEncodedValue.getValue().getDefiningClass().equals(containingClass)) {
|
||||
useImplicitReference = true;
|
||||
}
|
||||
ReferenceUtil.writeMethodDescriptor(writer, methodEncodedValue.getValue(), useImplicitReference);
|
||||
return;
|
||||
case ValueType.NULL:
|
||||
writer.write("null");
|
||||
return;
|
||||
case ValueType.SHORT:
|
||||
ShortRenderer.writeTo(writer, ((ShortEncodedValue)encodedValue).getValue());
|
||||
return;
|
||||
case ValueType.STRING:
|
||||
ReferenceFormatter.writeStringReference(writer, ((StringEncodedValue)encodedValue).getValue());
|
||||
return;
|
||||
case ValueType.TYPE:
|
||||
writer.write(((TypeEncodedValue)encodedValue).getValue());
|
||||
}
|
||||
}
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 Ben Gruver (JesusFreke)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali.Adaptors;
|
||||
|
||||
import org.jf.baksmali.baksmaliOptions;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class EndTryLabelMethodItem extends LabelMethodItem {
|
||||
private int endTryAddress;
|
||||
|
||||
public EndTryLabelMethodItem(@Nonnull baksmaliOptions options, int codeAddress, int endTryAddress) {
|
||||
super(options, codeAddress, "try_end_");
|
||||
this.endTryAddress = endTryAddress;
|
||||
}
|
||||
|
||||
public double getSortOrder() {
|
||||
//sort after instruction, but before catch directive
|
||||
return 101;
|
||||
}
|
||||
|
||||
public int getLabelAddress() {
|
||||
return endTryAddress;
|
||||
}
|
||||
}
|
@ -1,101 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 Ben Gruver (JesusFreke)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali.Adaptors;
|
||||
|
||||
import org.jf.baksmali.Adaptors.EncodedValue.EncodedValueAdaptor;
|
||||
import org.jf.baksmali.baksmaliOptions;
|
||||
import org.jf.dexlib2.AccessFlags;
|
||||
import org.jf.dexlib2.iface.Annotation;
|
||||
import org.jf.dexlib2.iface.Field;
|
||||
import org.jf.dexlib2.iface.value.EncodedValue;
|
||||
import org.jf.dexlib2.util.EncodedValueUtils;
|
||||
import org.jf.util.IndentingWriter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
|
||||
public class FieldDefinition {
|
||||
public static void writeTo(baksmaliOptions options, IndentingWriter writer, Field field,
|
||||
boolean setInStaticConstructor) throws IOException {
|
||||
EncodedValue initialValue = field.getInitialValue();
|
||||
int accessFlags = field.getAccessFlags();
|
||||
|
||||
if (setInStaticConstructor &&
|
||||
AccessFlags.STATIC.isSet(accessFlags) &&
|
||||
AccessFlags.FINAL.isSet(accessFlags) &&
|
||||
initialValue != null) {
|
||||
if (!EncodedValueUtils.isDefaultValue(initialValue)) {
|
||||
writer.write("# The value of this static final field might be set in the static constructor\n");
|
||||
} else {
|
||||
// don't write out the default initial value for static final fields that get set in the static
|
||||
// constructor
|
||||
initialValue = null;
|
||||
}
|
||||
}
|
||||
|
||||
writer.write(".field ");
|
||||
writeAccessFlags(writer, field.getAccessFlags());
|
||||
writer.write(field.getName());
|
||||
writer.write(':');
|
||||
writer.write(field.getType());
|
||||
if (initialValue != null) {
|
||||
writer.write(" = ");
|
||||
|
||||
String containingClass = null;
|
||||
if (options.useImplicitReferences) {
|
||||
containingClass = field.getDefiningClass();
|
||||
}
|
||||
|
||||
EncodedValueAdaptor.writeTo(writer, initialValue, containingClass);
|
||||
}
|
||||
|
||||
writer.write('\n');
|
||||
|
||||
Collection<? extends Annotation> annotations = field.getAnnotations();
|
||||
if (annotations.size() > 0) {
|
||||
writer.indent(4);
|
||||
|
||||
String containingClass = null;
|
||||
if (options.useImplicitReferences) {
|
||||
containingClass = field.getDefiningClass();
|
||||
}
|
||||
|
||||
AnnotationFormatter.writeTo(writer, annotations, containingClass);
|
||||
writer.deindent(4);
|
||||
writer.write(".end field\n");
|
||||
}
|
||||
}
|
||||
|
||||
private static void writeAccessFlags(IndentingWriter writer, int accessFlags) throws IOException {
|
||||
for (AccessFlags accessFlag: AccessFlags.getAccessFlagsForField(accessFlags)) {
|
||||
writer.write(accessFlag.toString());
|
||||
writer.write(' ');
|
||||
}
|
||||
}
|
||||
}
|
@ -1,81 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 Ben Gruver (JesusFreke)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali.Adaptors.Format;
|
||||
|
||||
import org.jf.baksmali.Adaptors.MethodDefinition;
|
||||
import org.jf.baksmali.Renderers.LongRenderer;
|
||||
import org.jf.dexlib2.iface.instruction.formats.ArrayPayload;
|
||||
import org.jf.util.IndentingWriter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
public class ArrayDataMethodItem extends InstructionMethodItem<ArrayPayload> {
|
||||
public ArrayDataMethodItem(MethodDefinition methodDef, int codeAddress, ArrayPayload instruction) {
|
||||
super(methodDef, codeAddress, instruction);
|
||||
}
|
||||
|
||||
public boolean writeTo(IndentingWriter writer) throws IOException {
|
||||
int elementWidth = instruction.getElementWidth();
|
||||
|
||||
writer.write(".array-data ");
|
||||
writer.printSignedIntAsDec(instruction.getElementWidth());
|
||||
writer.write('\n');
|
||||
|
||||
writer.indent(4);
|
||||
|
||||
List<Number> elements = instruction.getArrayElements();
|
||||
|
||||
String suffix = "";
|
||||
switch (elementWidth) {
|
||||
case 1:
|
||||
suffix = "t";
|
||||
break;
|
||||
case 2:
|
||||
suffix = "s";
|
||||
break;
|
||||
}
|
||||
|
||||
for (Number number: elements) {
|
||||
LongRenderer.writeSignedIntOrLongTo(writer, number.longValue());
|
||||
writer.write(suffix);
|
||||
if (elementWidth == 8) {
|
||||
writeCommentIfLikelyDouble(writer, number.longValue());
|
||||
} else if (elementWidth == 4) {
|
||||
int value = number.intValue();
|
||||
boolean isResourceId = writeCommentIfResourceId(writer, value);
|
||||
if (!isResourceId) writeCommentIfLikelyFloat(writer, value);
|
||||
}
|
||||
writer.write("\n");
|
||||
}
|
||||
writer.deindent(4);
|
||||
writer.write(".end array-data");
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,576 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 Ben Gruver (JesusFreke)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali.Adaptors.Format;
|
||||
|
||||
import org.jf.baksmali.Adaptors.MethodDefinition;
|
||||
import org.jf.baksmali.Adaptors.MethodDefinition.InvalidSwitchPayload;
|
||||
import org.jf.baksmali.Adaptors.MethodItem;
|
||||
import org.jf.baksmali.Renderers.LongRenderer;
|
||||
import org.jf.baksmali.baksmaliOptions;
|
||||
import org.jf.dexlib2.Opcode;
|
||||
import org.jf.dexlib2.ReferenceType;
|
||||
import org.jf.dexlib2.VerificationError;
|
||||
import org.jf.dexlib2.dexbacked.DexBackedDexFile.InvalidItemIndex;
|
||||
import org.jf.dexlib2.iface.instruction.*;
|
||||
import org.jf.dexlib2.iface.instruction.formats.Instruction20bc;
|
||||
import org.jf.dexlib2.iface.instruction.formats.Instruction31t;
|
||||
import org.jf.dexlib2.iface.instruction.formats.UnknownInstruction;
|
||||
import org.jf.dexlib2.iface.reference.Reference;
|
||||
import org.jf.dexlib2.util.ReferenceUtil;
|
||||
import org.jf.util.ExceptionWithContext;
|
||||
import org.jf.util.IndentingWriter;
|
||||
import org.jf.util.NumberUtils;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
public class InstructionMethodItem<T extends Instruction> extends MethodItem {
|
||||
@Nonnull protected final MethodDefinition methodDef;
|
||||
@Nonnull protected final T instruction;
|
||||
|
||||
public InstructionMethodItem(@Nonnull MethodDefinition methodDef, int codeAddress, @Nonnull T instruction) {
|
||||
super(codeAddress);
|
||||
this.methodDef = methodDef;
|
||||
this.instruction = instruction;
|
||||
}
|
||||
|
||||
public double getSortOrder() {
|
||||
//instructions should appear after everything except an "end try" label and .catch directive
|
||||
return 100;
|
||||
}
|
||||
|
||||
private boolean isAllowedOdex(@Nonnull Opcode opcode) {
|
||||
baksmaliOptions options = methodDef.classDef.options;
|
||||
if (options.allowOdex) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (methodDef.classDef.options.apiLevel >= 14) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return opcode.isOdexedInstanceVolatile() || opcode.isOdexedStaticVolatile() ||
|
||||
opcode == Opcode.THROW_VERIFICATION_ERROR;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean writeTo(IndentingWriter writer) throws IOException {
|
||||
Opcode opcode = instruction.getOpcode();
|
||||
String verificationErrorName = null;
|
||||
String referenceString = null;
|
||||
|
||||
boolean commentOutInstruction = false;
|
||||
|
||||
if (instruction instanceof Instruction20bc) {
|
||||
int verificationError = ((Instruction20bc)instruction).getVerificationError();
|
||||
verificationErrorName = VerificationError.getVerificationErrorName(verificationError);
|
||||
if (verificationErrorName == null) {
|
||||
writer.write("#was invalid verification error type: ");
|
||||
writer.printSignedIntAsDec(verificationError);
|
||||
writer.write("\n");
|
||||
verificationErrorName = "generic-error";
|
||||
}
|
||||
}
|
||||
|
||||
if (instruction instanceof ReferenceInstruction) {
|
||||
ReferenceInstruction referenceInstruction = (ReferenceInstruction)instruction;
|
||||
try {
|
||||
Reference reference = referenceInstruction.getReference();
|
||||
|
||||
String classContext = null;
|
||||
if (methodDef.classDef.options.useImplicitReferences) {
|
||||
classContext = methodDef.method.getDefiningClass();
|
||||
}
|
||||
|
||||
referenceString = ReferenceUtil.getReferenceString(reference, classContext);
|
||||
assert referenceString != null;
|
||||
} catch (InvalidItemIndex ex) {
|
||||
writer.write("#");
|
||||
writer.write(ex.getMessage());
|
||||
writer.write("\n");
|
||||
commentOutInstruction = true;
|
||||
|
||||
referenceString = String.format("%s@%d",
|
||||
ReferenceType.toString(referenceInstruction.getReferenceType()),
|
||||
ex.getInvalidIndex());
|
||||
} catch (ReferenceType.InvalidReferenceTypeException ex) {
|
||||
writer.write("#invalid reference type: ");
|
||||
writer.printSignedIntAsDec(ex.getReferenceType());
|
||||
commentOutInstruction = true;
|
||||
|
||||
referenceString = "invalid_reference";
|
||||
}
|
||||
}
|
||||
|
||||
if (instruction instanceof Instruction31t) {
|
||||
boolean validPayload = true;
|
||||
|
||||
switch (instruction.getOpcode()) {
|
||||
case PACKED_SWITCH:
|
||||
int baseAddress = methodDef.getPackedSwitchBaseAddress(
|
||||
this.codeAddress + ((Instruction31t)instruction).getCodeOffset());
|
||||
if (baseAddress == -1) {
|
||||
validPayload = false;
|
||||
}
|
||||
break;
|
||||
case SPARSE_SWITCH:
|
||||
baseAddress = methodDef.getSparseSwitchBaseAddress(
|
||||
this.codeAddress + ((Instruction31t)instruction).getCodeOffset());
|
||||
if (baseAddress == -1) {
|
||||
validPayload = false;
|
||||
}
|
||||
break;
|
||||
case FILL_ARRAY_DATA:
|
||||
try {
|
||||
methodDef.findPayloadOffset(this.codeAddress + ((Instruction31t)instruction).getCodeOffset(),
|
||||
Opcode.ARRAY_PAYLOAD);
|
||||
} catch (InvalidSwitchPayload ex) {
|
||||
validPayload = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new ExceptionWithContext("Invalid 31t opcode: %s", instruction.getOpcode());
|
||||
}
|
||||
|
||||
if (!validPayload) {
|
||||
writer.write("#invalid payload reference\n");
|
||||
commentOutInstruction = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (opcode.odexOnly()) {
|
||||
if (!isAllowedOdex(opcode)) {
|
||||
writer.write("#disallowed odex opcode\n");
|
||||
commentOutInstruction = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (commentOutInstruction) {
|
||||
writer.write("#");
|
||||
}
|
||||
|
||||
switch (instruction.getOpcode().format) {
|
||||
case Format10t:
|
||||
writeOpcode(writer);
|
||||
writer.write(' ');
|
||||
writeTargetLabel(writer);
|
||||
break;
|
||||
case Format10x:
|
||||
if (instruction instanceof UnknownInstruction) {
|
||||
writer.write("#unknown opcode: 0x");
|
||||
writer.printUnsignedLongAsHex(((UnknownInstruction)instruction).getOriginalOpcode());
|
||||
writer.write('\n');
|
||||
}
|
||||
writeOpcode(writer);
|
||||
break;
|
||||
case Format11n:
|
||||
writeOpcode(writer);
|
||||
writer.write(' ');
|
||||
writeFirstRegister(writer);
|
||||
writer.write(", ");
|
||||
writeLiteral(writer);
|
||||
break;
|
||||
case Format11x:
|
||||
writeOpcode(writer);
|
||||
writer.write(' ');
|
||||
writeFirstRegister(writer);
|
||||
break;
|
||||
case Format12x:
|
||||
writeOpcode(writer);
|
||||
writer.write(' ');
|
||||
writeFirstRegister(writer);
|
||||
writer.write(", ");
|
||||
writeSecondRegister(writer);
|
||||
break;
|
||||
case Format20bc:
|
||||
writeOpcode(writer);
|
||||
writer.write(' ');
|
||||
writer.write(verificationErrorName);
|
||||
writer.write(", ");
|
||||
writer.write(referenceString);
|
||||
break;
|
||||
case Format20t:
|
||||
case Format30t:
|
||||
writeOpcode(writer);
|
||||
writer.write(' ');
|
||||
writeTargetLabel(writer);
|
||||
break;
|
||||
case Format21c:
|
||||
case Format31c:
|
||||
writeOpcode(writer);
|
||||
writer.write(' ');
|
||||
writeFirstRegister(writer);
|
||||
writer.write(", ");
|
||||
writer.write(referenceString);
|
||||
break;
|
||||
case Format21ih:
|
||||
case Format21lh:
|
||||
case Format21s:
|
||||
case Format31i:
|
||||
case Format51l:
|
||||
writeOpcode(writer);
|
||||
writer.write(' ');
|
||||
writeFirstRegister(writer);
|
||||
writer.write(", ");
|
||||
writeLiteral(writer);
|
||||
if (instruction.getOpcode().setsWideRegister()) {
|
||||
writeCommentIfLikelyDouble(writer);
|
||||
} else {
|
||||
boolean isResourceId = writeCommentIfResourceId(writer);
|
||||
if (!isResourceId) writeCommentIfLikelyFloat(writer);
|
||||
}
|
||||
break;
|
||||
case Format21t:
|
||||
case Format31t:
|
||||
writeOpcode(writer);
|
||||
writer.write(' ');
|
||||
writeFirstRegister(writer);
|
||||
writer.write(", ");
|
||||
writeTargetLabel(writer);
|
||||
break;
|
||||
case Format22b:
|
||||
case Format22s:
|
||||
writeOpcode(writer);
|
||||
writer.write(' ');
|
||||
writeFirstRegister(writer);
|
||||
writer.write(", ");
|
||||
writeSecondRegister(writer);
|
||||
writer.write(", ");
|
||||
writeLiteral(writer);
|
||||
break;
|
||||
case Format22c:
|
||||
writeOpcode(writer);
|
||||
writer.write(' ');
|
||||
writeFirstRegister(writer);
|
||||
writer.write(", ");
|
||||
writeSecondRegister(writer);
|
||||
writer.write(", ");
|
||||
writer.write(referenceString);
|
||||
break;
|
||||
case Format22cs:
|
||||
writeOpcode(writer);
|
||||
writer.write(' ');
|
||||
writeFirstRegister(writer);
|
||||
writer.write(", ");
|
||||
writeSecondRegister(writer);
|
||||
writer.write(", ");
|
||||
writeFieldOffset(writer);
|
||||
break;
|
||||
case Format22t:
|
||||
writeOpcode(writer);
|
||||
writer.write(' ');
|
||||
writeFirstRegister(writer);
|
||||
writer.write(", ");
|
||||
writeSecondRegister(writer);
|
||||
writer.write(", ");
|
||||
writeTargetLabel(writer);
|
||||
break;
|
||||
case Format22x:
|
||||
case Format32x:
|
||||
writeOpcode(writer);
|
||||
writer.write(' ');
|
||||
writeFirstRegister(writer);
|
||||
writer.write(", ");
|
||||
writeSecondRegister(writer);
|
||||
break;
|
||||
case Format23x:
|
||||
writeOpcode(writer);
|
||||
writer.write(' ');
|
||||
writeFirstRegister(writer);
|
||||
writer.write(", ");
|
||||
writeSecondRegister(writer);
|
||||
writer.write(", ");
|
||||
writeThirdRegister(writer);
|
||||
break;
|
||||
case Format25x:
|
||||
writeOpcode(writer);
|
||||
writer.write(' ');
|
||||
writeInvoke25xRegisters(writer); // vC, {vD, ...}
|
||||
break;
|
||||
case Format35c:
|
||||
writeOpcode(writer);
|
||||
writer.write(' ');
|
||||
writeInvokeRegisters(writer);
|
||||
writer.write(", ");
|
||||
writer.write(referenceString);
|
||||
break;
|
||||
case Format35mi:
|
||||
writeOpcode(writer);
|
||||
writer.write(' ');
|
||||
writeInvokeRegisters(writer);
|
||||
writer.write(", ");
|
||||
writeInlineIndex(writer);
|
||||
break;
|
||||
case Format35ms:
|
||||
writeOpcode(writer);
|
||||
writer.write(' ');
|
||||
writeInvokeRegisters(writer);
|
||||
writer.write(", ");
|
||||
writeVtableIndex(writer);
|
||||
break;
|
||||
case Format3rc:
|
||||
writeOpcode(writer);
|
||||
writer.write(' ');
|
||||
writeInvokeRangeRegisters(writer);
|
||||
writer.write(", ");
|
||||
writer.write(referenceString);
|
||||
break;
|
||||
case Format3rmi:
|
||||
writeOpcode(writer);
|
||||
writer.write(' ');
|
||||
writeInvokeRangeRegisters(writer);
|
||||
writer.write(", ");
|
||||
writeInlineIndex(writer);
|
||||
break;
|
||||
case Format3rms:
|
||||
writeOpcode(writer);
|
||||
writer.write(' ');
|
||||
writeInvokeRangeRegisters(writer);
|
||||
writer.write(", ");
|
||||
writeVtableIndex(writer);
|
||||
break;
|
||||
default:
|
||||
assert false;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (commentOutInstruction) {
|
||||
writer.write("\nnop");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void writeOpcode(IndentingWriter writer) throws IOException {
|
||||
writer.write(instruction.getOpcode().name);
|
||||
}
|
||||
|
||||
protected void writeTargetLabel(IndentingWriter writer) throws IOException {
|
||||
//this method is overridden by OffsetInstructionMethodItem, and should only be called for the formats that
|
||||
//have a target
|
||||
throw new RuntimeException();
|
||||
}
|
||||
|
||||
protected void writeRegister(IndentingWriter writer, int registerNumber) throws IOException {
|
||||
methodDef.registerFormatter.writeTo(writer, registerNumber);
|
||||
}
|
||||
|
||||
protected void writeFirstRegister(IndentingWriter writer) throws IOException {
|
||||
writeRegister(writer, ((OneRegisterInstruction)instruction).getRegisterA());
|
||||
}
|
||||
|
||||
protected void writeSecondRegister(IndentingWriter writer) throws IOException {
|
||||
writeRegister(writer, ((TwoRegisterInstruction)instruction).getRegisterB());
|
||||
}
|
||||
|
||||
protected void writeThirdRegister(IndentingWriter writer) throws IOException {
|
||||
writeRegister(writer, ((ThreeRegisterInstruction) instruction).getRegisterC());
|
||||
}
|
||||
|
||||
protected void writeInvokeRegisters(IndentingWriter writer) throws IOException {
|
||||
FiveRegisterInstruction instruction = (FiveRegisterInstruction)this.instruction;
|
||||
final int regCount = instruction.getRegisterCount();
|
||||
|
||||
writer.write('{');
|
||||
switch (regCount) {
|
||||
case 1:
|
||||
writeRegister(writer, instruction.getRegisterC());
|
||||
break;
|
||||
case 2:
|
||||
writeRegister(writer, instruction.getRegisterC());
|
||||
writer.write(", ");
|
||||
writeRegister(writer, instruction.getRegisterD());
|
||||
break;
|
||||
case 3:
|
||||
writeRegister(writer, instruction.getRegisterC());
|
||||
writer.write(", ");
|
||||
writeRegister(writer, instruction.getRegisterD());
|
||||
writer.write(", ");
|
||||
writeRegister(writer, instruction.getRegisterE());
|
||||
break;
|
||||
case 4:
|
||||
writeRegister(writer, instruction.getRegisterC());
|
||||
writer.write(", ");
|
||||
writeRegister(writer, instruction.getRegisterD());
|
||||
writer.write(", ");
|
||||
writeRegister(writer, instruction.getRegisterE());
|
||||
writer.write(", ");
|
||||
writeRegister(writer, instruction.getRegisterF());
|
||||
break;
|
||||
case 5:
|
||||
writeRegister(writer, instruction.getRegisterC());
|
||||
writer.write(", ");
|
||||
writeRegister(writer, instruction.getRegisterD());
|
||||
writer.write(", ");
|
||||
writeRegister(writer, instruction.getRegisterE());
|
||||
writer.write(", ");
|
||||
writeRegister(writer, instruction.getRegisterF());
|
||||
writer.write(", ");
|
||||
writeRegister(writer, instruction.getRegisterG());
|
||||
break;
|
||||
}
|
||||
writer.write('}');
|
||||
}
|
||||
|
||||
protected void writeInvoke25xRegisters(IndentingWriter writer) throws IOException {
|
||||
OneFixedFourParameterRegisterInstruction instruction =
|
||||
(OneFixedFourParameterRegisterInstruction)this.instruction;
|
||||
final int parameterRegCount = instruction.getParameterRegisterCount();
|
||||
|
||||
writeRegister(writer, instruction.getRegisterFixedC()); // fixed register always present
|
||||
|
||||
writer.write(", {");
|
||||
switch (parameterRegCount) {
|
||||
case 1:
|
||||
writeRegister(writer, instruction.getRegisterParameterD());
|
||||
break;
|
||||
case 2:
|
||||
writeRegister(writer, instruction.getRegisterParameterD());
|
||||
writer.write(", ");
|
||||
writeRegister(writer, instruction.getRegisterParameterE());
|
||||
break;
|
||||
case 3:
|
||||
writeRegister(writer, instruction.getRegisterParameterD());
|
||||
writer.write(", ");
|
||||
writeRegister(writer, instruction.getRegisterParameterE());
|
||||
writer.write(", ");
|
||||
writeRegister(writer, instruction.getRegisterParameterF());
|
||||
break;
|
||||
case 4:
|
||||
writeRegister(writer, instruction.getRegisterParameterD());
|
||||
writer.write(", ");
|
||||
writeRegister(writer, instruction.getRegisterParameterE());
|
||||
writer.write(", ");
|
||||
writeRegister(writer, instruction.getRegisterParameterF());
|
||||
writer.write(", ");
|
||||
writeRegister(writer, instruction.getRegisterParameterG());
|
||||
break;
|
||||
}
|
||||
writer.write('}');
|
||||
}
|
||||
|
||||
protected void writeInvokeRangeRegisters(IndentingWriter writer) throws IOException {
|
||||
RegisterRangeInstruction instruction = (RegisterRangeInstruction)this.instruction;
|
||||
|
||||
int regCount = instruction.getRegisterCount();
|
||||
if (regCount == 0) {
|
||||
writer.write("{}");
|
||||
} else {
|
||||
int startRegister = instruction.getStartRegister();
|
||||
methodDef.registerFormatter.writeRegisterRange(writer, startRegister, startRegister+regCount-1);
|
||||
}
|
||||
}
|
||||
|
||||
protected void writeLiteral(IndentingWriter writer) throws IOException {
|
||||
LongRenderer.writeSignedIntOrLongTo(writer, ((WideLiteralInstruction)instruction).getWideLiteral());
|
||||
}
|
||||
|
||||
protected void writeCommentIfLikelyFloat(IndentingWriter writer) throws IOException {
|
||||
writeCommentIfLikelyFloat(writer, ((NarrowLiteralInstruction)instruction).getNarrowLiteral());
|
||||
}
|
||||
|
||||
protected void writeCommentIfLikelyFloat(IndentingWriter writer, int val) throws IOException {
|
||||
if (NumberUtils.isLikelyFloat(val)) {
|
||||
writer.write(" # ");
|
||||
float fval = Float.intBitsToFloat(val);
|
||||
if (fval == Float.POSITIVE_INFINITY)
|
||||
writer.write("Float.POSITIVE_INFINITY");
|
||||
else if (fval == Float.NEGATIVE_INFINITY)
|
||||
writer.write("Float.NEGATIVE_INFINITY");
|
||||
else if (fval == Float.NaN)
|
||||
writer.write("Float.NaN");
|
||||
else if (fval == Float.MAX_VALUE)
|
||||
writer.write("Float.MAX_VALUE");
|
||||
else if (fval == (float)Math.PI)
|
||||
writer.write("(float)Math.PI");
|
||||
else if (fval == (float)Math.E)
|
||||
writer.write("(float)Math.E");
|
||||
else {
|
||||
writer.write(Float.toString(fval));
|
||||
writer.write('f');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void writeCommentIfLikelyDouble(IndentingWriter writer) throws IOException {
|
||||
writeCommentIfLikelyDouble(writer, ((WideLiteralInstruction)instruction).getWideLiteral());
|
||||
}
|
||||
|
||||
protected void writeCommentIfLikelyDouble(IndentingWriter writer, long val) throws IOException {
|
||||
if (NumberUtils.isLikelyDouble(val)) {
|
||||
writer.write(" # ");
|
||||
double dval = Double.longBitsToDouble(val);
|
||||
if (dval == Double.POSITIVE_INFINITY)
|
||||
writer.write("Double.POSITIVE_INFINITY");
|
||||
else if (dval == Double.NEGATIVE_INFINITY)
|
||||
writer.write("Double.NEGATIVE_INFINITY");
|
||||
else if (dval == Double.NaN)
|
||||
writer.write("Double.NaN");
|
||||
else if (dval == Double.MAX_VALUE)
|
||||
writer.write("Double.MAX_VALUE");
|
||||
else if (dval == Math.PI)
|
||||
writer.write("Math.PI");
|
||||
else if (dval == Math.E)
|
||||
writer.write("Math.E");
|
||||
else
|
||||
writer.write(Double.toString(dval));
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean writeCommentIfResourceId(IndentingWriter writer) throws IOException {
|
||||
return writeCommentIfResourceId(writer, ((NarrowLiteralInstruction)instruction).getNarrowLiteral());
|
||||
}
|
||||
|
||||
protected boolean writeCommentIfResourceId(IndentingWriter writer, int val) throws IOException {
|
||||
Map<Integer,String> resourceIds = methodDef.classDef.options.resourceIds;
|
||||
String resource = resourceIds.get(Integer.valueOf(val));
|
||||
if (resource != null) {
|
||||
writer.write(" # ");
|
||||
writer.write(resource);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void writeFieldOffset(IndentingWriter writer) throws IOException {
|
||||
writer.write("field@0x");
|
||||
writer.printUnsignedLongAsHex(((FieldOffsetInstruction)instruction).getFieldOffset());
|
||||
}
|
||||
|
||||
protected void writeInlineIndex(IndentingWriter writer) throws IOException {
|
||||
writer.write("inline@");
|
||||
writer.printSignedIntAsDec(((InlineIndexInstruction)instruction).getInlineIndex());
|
||||
}
|
||||
|
||||
protected void writeVtableIndex(IndentingWriter writer) throws IOException {
|
||||
writer.write("vtable@");
|
||||
writer.printSignedIntAsDec(((VtableIndexInstruction)instruction).getVtableIndex());
|
||||
}
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 Ben Gruver (JesusFreke)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali.Adaptors.Format;
|
||||
|
||||
import org.jf.baksmali.Adaptors.MethodDefinition;
|
||||
import org.jf.dexlib2.analysis.UnresolvedOdexInstruction;
|
||||
import org.jf.dexlib2.iface.instruction.Instruction;
|
||||
import org.jf.dexlib2.iface.instruction.OffsetInstruction;
|
||||
import org.jf.dexlib2.iface.instruction.formats.ArrayPayload;
|
||||
import org.jf.dexlib2.iface.instruction.formats.PackedSwitchPayload;
|
||||
import org.jf.dexlib2.iface.instruction.formats.SparseSwitchPayload;
|
||||
|
||||
public class InstructionMethodItemFactory {
|
||||
private InstructionMethodItemFactory() {
|
||||
}
|
||||
|
||||
public static InstructionMethodItem makeInstructionFormatMethodItem(
|
||||
MethodDefinition methodDef, int codeAddress, Instruction instruction) {
|
||||
|
||||
if (instruction instanceof OffsetInstruction) {
|
||||
return new OffsetInstructionFormatMethodItem(methodDef.classDef.options, methodDef, codeAddress,
|
||||
(OffsetInstruction)instruction);
|
||||
}
|
||||
|
||||
if (instruction instanceof UnresolvedOdexInstruction) {
|
||||
return new UnresolvedOdexInstructionMethodItem(methodDef, codeAddress,
|
||||
(UnresolvedOdexInstruction)instruction);
|
||||
}
|
||||
|
||||
switch (instruction.getOpcode().format) {
|
||||
case ArrayPayload:
|
||||
return new ArrayDataMethodItem(methodDef, codeAddress, (ArrayPayload)instruction);
|
||||
case PackedSwitchPayload:
|
||||
return new PackedSwitchMethodItem(methodDef, codeAddress, (PackedSwitchPayload)instruction);
|
||||
case SparseSwitchPayload:
|
||||
return new SparseSwitchMethodItem(methodDef, codeAddress, (SparseSwitchPayload)instruction);
|
||||
default:
|
||||
return new InstructionMethodItem<Instruction>(methodDef, codeAddress, instruction);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,85 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 Ben Gruver (JesusFreke)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali.Adaptors.Format;
|
||||
|
||||
import org.jf.baksmali.Adaptors.LabelMethodItem;
|
||||
import org.jf.baksmali.Adaptors.MethodDefinition;
|
||||
import org.jf.baksmali.baksmaliOptions;
|
||||
import org.jf.dexlib2.Opcode;
|
||||
import org.jf.dexlib2.iface.instruction.OffsetInstruction;
|
||||
import org.jf.util.IndentingWriter;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.io.IOException;
|
||||
|
||||
public class OffsetInstructionFormatMethodItem extends InstructionMethodItem<OffsetInstruction> {
|
||||
protected LabelMethodItem label;
|
||||
|
||||
public OffsetInstructionFormatMethodItem(@Nonnull baksmaliOptions options, @Nonnull MethodDefinition methodDef,
|
||||
int codeAddress, OffsetInstruction instruction) {
|
||||
super(methodDef, codeAddress, instruction);
|
||||
|
||||
label = new LabelMethodItem(options, codeAddress + instruction.getCodeOffset(), getLabelPrefix());
|
||||
label = methodDef.getLabelCache().internLabel(label);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeTargetLabel(IndentingWriter writer) throws IOException {
|
||||
label.writeTo(writer);
|
||||
}
|
||||
|
||||
public LabelMethodItem getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
private String getLabelPrefix() {
|
||||
Opcode opcode = instruction.getOpcode();
|
||||
switch (opcode.format) {
|
||||
case Format10t:
|
||||
case Format20t:
|
||||
case Format30t:
|
||||
return "goto_";
|
||||
case Format21t:
|
||||
case Format22t:
|
||||
return "cond_";
|
||||
case Format31t:
|
||||
if (opcode == Opcode.FILL_ARRAY_DATA) {
|
||||
return "array_";
|
||||
}
|
||||
if (opcode == Opcode.PACKED_SWITCH) {
|
||||
return "pswitch_data_";
|
||||
}
|
||||
// Opcode.SPARSE_SWITCH;
|
||||
return "sswitch_data_";
|
||||
}
|
||||
|
||||
assert false;
|
||||
return null;
|
||||
}
|
||||
}
|
@ -1,130 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 Ben Gruver (JesusFreke)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali.Adaptors.Format;
|
||||
|
||||
import org.jf.baksmali.Adaptors.CommentingIndentingWriter;
|
||||
import org.jf.baksmali.Adaptors.LabelMethodItem;
|
||||
import org.jf.baksmali.Adaptors.MethodDefinition;
|
||||
import org.jf.dexlib2.iface.instruction.SwitchElement;
|
||||
import org.jf.dexlib2.iface.instruction.formats.PackedSwitchPayload;
|
||||
import org.jf.util.IndentingWriter;
|
||||
import org.jf.baksmali.Renderers.IntegerRenderer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class PackedSwitchMethodItem extends InstructionMethodItem<PackedSwitchPayload> {
|
||||
private final List<PackedSwitchTarget> targets;
|
||||
private final int firstKey;
|
||||
|
||||
// Whether this sparse switch instruction should be commented out because it is never referenced
|
||||
private boolean commentedOut;
|
||||
|
||||
public PackedSwitchMethodItem(MethodDefinition methodDef, int codeAddress, PackedSwitchPayload instruction) {
|
||||
super(methodDef, codeAddress, instruction);
|
||||
|
||||
int baseCodeAddress = methodDef.getPackedSwitchBaseAddress(codeAddress);
|
||||
|
||||
targets = new ArrayList<PackedSwitchTarget>();
|
||||
|
||||
boolean first = true;
|
||||
int firstKey = 0;
|
||||
if (baseCodeAddress >= 0) {
|
||||
for (SwitchElement switchElement: instruction.getSwitchElements()) {
|
||||
if (first) {
|
||||
firstKey = switchElement.getKey();
|
||||
first = false;
|
||||
}
|
||||
LabelMethodItem label = methodDef.getLabelCache().internLabel(
|
||||
new LabelMethodItem(methodDef.classDef.options, baseCodeAddress + switchElement.getOffset(),
|
||||
"pswitch_"));
|
||||
targets.add(new PackedSwitchLabelTarget(label));
|
||||
}
|
||||
} else {
|
||||
commentedOut = true;
|
||||
for (SwitchElement switchElement: instruction.getSwitchElements()) {
|
||||
if (first) {
|
||||
firstKey = switchElement.getKey();
|
||||
first = false;
|
||||
}
|
||||
targets.add(new PackedSwitchOffsetTarget(switchElement.getOffset()));
|
||||
}
|
||||
}
|
||||
this.firstKey = firstKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean writeTo(IndentingWriter writer) throws IOException {
|
||||
if (commentedOut) {
|
||||
writer = new CommentingIndentingWriter(writer);
|
||||
}
|
||||
writer.write(".packed-switch ");
|
||||
IntegerRenderer.writeTo(writer, firstKey);
|
||||
writer.indent(4);
|
||||
writer.write('\n');
|
||||
int key = firstKey;
|
||||
for (PackedSwitchTarget target: targets) {
|
||||
target.writeTargetTo(writer);
|
||||
writeCommentIfResourceId(writer, key);
|
||||
writer.write('\n');
|
||||
key++;
|
||||
}
|
||||
writer.deindent(4);
|
||||
writer.write(".end packed-switch");
|
||||
return true;
|
||||
}
|
||||
|
||||
private static abstract class PackedSwitchTarget {
|
||||
public abstract void writeTargetTo(IndentingWriter writer) throws IOException;
|
||||
}
|
||||
|
||||
private static class PackedSwitchLabelTarget extends PackedSwitchTarget {
|
||||
private final LabelMethodItem target;
|
||||
public PackedSwitchLabelTarget(LabelMethodItem target) {
|
||||
this.target = target;
|
||||
}
|
||||
public void writeTargetTo(IndentingWriter writer) throws IOException {
|
||||
target.writeTo(writer);
|
||||
}
|
||||
}
|
||||
|
||||
private static class PackedSwitchOffsetTarget extends PackedSwitchTarget {
|
||||
private final int target;
|
||||
public PackedSwitchOffsetTarget(int target) {
|
||||
this.target = target;
|
||||
}
|
||||
public void writeTargetTo(IndentingWriter writer) throws IOException {
|
||||
if (target >= 0) {
|
||||
writer.write('+');
|
||||
}
|
||||
writer.printSignedIntAsDec(target);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,126 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 Ben Gruver (JesusFreke)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali.Adaptors.Format;
|
||||
|
||||
import org.jf.baksmali.Adaptors.CommentingIndentingWriter;
|
||||
import org.jf.baksmali.Adaptors.LabelMethodItem;
|
||||
import org.jf.baksmali.Adaptors.MethodDefinition;
|
||||
import org.jf.dexlib2.iface.instruction.SwitchElement;
|
||||
import org.jf.dexlib2.iface.instruction.formats.SparseSwitchPayload;
|
||||
import org.jf.util.IndentingWriter;
|
||||
import org.jf.baksmali.Renderers.IntegerRenderer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class SparseSwitchMethodItem extends InstructionMethodItem<SparseSwitchPayload> {
|
||||
private final List<SparseSwitchTarget> targets;
|
||||
|
||||
// Whether this sparse switch instruction should be commented out because it is never referenced
|
||||
private boolean commentedOut;
|
||||
|
||||
public SparseSwitchMethodItem(MethodDefinition methodDef, int codeAddress, SparseSwitchPayload instruction) {
|
||||
super(methodDef, codeAddress, instruction);
|
||||
|
||||
int baseCodeAddress = methodDef.getSparseSwitchBaseAddress(codeAddress);
|
||||
|
||||
targets = new ArrayList<SparseSwitchTarget>();
|
||||
if (baseCodeAddress >= 0) {
|
||||
for (SwitchElement switchElement: instruction.getSwitchElements()) {
|
||||
LabelMethodItem label = methodDef.getLabelCache().internLabel(
|
||||
new LabelMethodItem( methodDef.classDef.options, baseCodeAddress + switchElement.getOffset(),
|
||||
"sswitch_"));
|
||||
targets.add(new SparseSwitchLabelTarget(switchElement.getKey(), label));
|
||||
}
|
||||
} else {
|
||||
commentedOut = true;
|
||||
//if we couldn't determine a base address, just use relative offsets rather than labels
|
||||
for (SwitchElement switchElement: instruction.getSwitchElements()) {
|
||||
targets.add(new SparseSwitchOffsetTarget(switchElement.getKey(), switchElement.getOffset()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean writeTo(IndentingWriter writer) throws IOException {
|
||||
if (commentedOut) {
|
||||
writer = new CommentingIndentingWriter(writer);
|
||||
}
|
||||
|
||||
writer.write(".sparse-switch\n");
|
||||
writer.indent(4);
|
||||
for (SparseSwitchTarget target: targets) {
|
||||
IntegerRenderer.writeTo(writer, target.getKey());
|
||||
writer.write(" -> ");
|
||||
target.writeTargetTo(writer);
|
||||
writeCommentIfResourceId(writer, target.getKey());
|
||||
writer.write('\n');
|
||||
}
|
||||
writer.deindent(4);
|
||||
writer.write(".end sparse-switch");
|
||||
return true;
|
||||
}
|
||||
|
||||
private static abstract class SparseSwitchTarget {
|
||||
private final int key;
|
||||
public SparseSwitchTarget(int key) {
|
||||
this.key = key;
|
||||
}
|
||||
public int getKey() { return key; }
|
||||
public abstract void writeTargetTo(IndentingWriter writer) throws IOException;
|
||||
}
|
||||
|
||||
private static class SparseSwitchLabelTarget extends SparseSwitchTarget {
|
||||
private final LabelMethodItem target;
|
||||
public SparseSwitchLabelTarget(int key, LabelMethodItem target) {
|
||||
super(key);
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
public void writeTargetTo(IndentingWriter writer) throws IOException {
|
||||
target.writeTo(writer);
|
||||
}
|
||||
}
|
||||
|
||||
private static class SparseSwitchOffsetTarget extends SparseSwitchTarget {
|
||||
private final int target;
|
||||
public SparseSwitchOffsetTarget(int key, int target) {
|
||||
super(key);
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
public void writeTargetTo(IndentingWriter writer) throws IOException {
|
||||
if (target >= 0) {
|
||||
writer.write('+');
|
||||
}
|
||||
writer.printSignedIntAsDec(target);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 Ben Gruver (JesusFreke)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali.Adaptors.Format;
|
||||
|
||||
import org.jf.baksmali.Adaptors.MethodDefinition;
|
||||
import org.jf.dexlib2.analysis.UnresolvedOdexInstruction;
|
||||
import org.jf.util.IndentingWriter;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.io.IOException;
|
||||
|
||||
public class UnresolvedOdexInstructionMethodItem extends InstructionMethodItem<UnresolvedOdexInstruction> {
|
||||
public UnresolvedOdexInstructionMethodItem(@Nonnull MethodDefinition methodDef, int codeAddress,
|
||||
@Nonnull UnresolvedOdexInstruction instruction) {
|
||||
super(methodDef, codeAddress, instruction);
|
||||
}
|
||||
|
||||
public boolean writeTo(IndentingWriter writer) throws IOException {
|
||||
writeThrowTo(writer);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void writeThrowTo(IndentingWriter writer) throws IOException {
|
||||
writer.write("#Replaced unresolvable odex instruction with a throw\n");
|
||||
writer.write("throw ");
|
||||
writeRegister(writer, instruction.objectRegisterNum);
|
||||
}
|
||||
}
|
@ -1,102 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 Ben Gruver (JesusFreke)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali.Adaptors;
|
||||
|
||||
import org.jf.baksmali.baksmaliOptions;
|
||||
import org.jf.util.IndentingWriter;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.io.IOException;
|
||||
|
||||
public class LabelMethodItem extends MethodItem {
|
||||
private final baksmaliOptions options;
|
||||
private final String labelPrefix;
|
||||
private int labelSequence;
|
||||
|
||||
public LabelMethodItem(@Nonnull baksmaliOptions options, int codeAddress, @Nonnull String labelPrefix) {
|
||||
super(codeAddress);
|
||||
this.options = options;
|
||||
this.labelPrefix = labelPrefix;
|
||||
}
|
||||
|
||||
public double getSortOrder() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int compareTo(MethodItem methodItem) {
|
||||
int result = super.compareTo(methodItem);
|
||||
|
||||
if (result == 0) {
|
||||
if (methodItem instanceof LabelMethodItem) {
|
||||
result = labelPrefix.compareTo(((LabelMethodItem)methodItem).labelPrefix);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
//force it to call equals when two labels are at the same address
|
||||
return getCodeAddress();
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof LabelMethodItem)) {
|
||||
return false;
|
||||
}
|
||||
return this.compareTo((MethodItem)o) == 0;
|
||||
}
|
||||
|
||||
|
||||
public boolean writeTo(IndentingWriter writer) throws IOException {
|
||||
writer.write(':');
|
||||
writer.write(labelPrefix);
|
||||
if (options.useSequentialLabels) {
|
||||
writer.printUnsignedLongAsHex(labelSequence);
|
||||
} else {
|
||||
writer.printUnsignedLongAsHex(this.getLabelAddress());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public String getLabelPrefix() {
|
||||
return labelPrefix;
|
||||
}
|
||||
|
||||
public int getLabelAddress() {
|
||||
return this.getCodeAddress();
|
||||
}
|
||||
|
||||
public int getLabelSequence() {
|
||||
return labelSequence;
|
||||
}
|
||||
|
||||
public void setLabelSequence(int labelSequence) {
|
||||
this.labelSequence = labelSequence;
|
||||
}
|
||||
}
|
@ -1,638 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 Ben Gruver (JesusFreke)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali.Adaptors;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Lists;
|
||||
import org.jf.baksmali.Adaptors.Debug.DebugMethodItem;
|
||||
import org.jf.baksmali.Adaptors.Format.InstructionMethodItemFactory;
|
||||
import org.jf.baksmali.baksmaliOptions;
|
||||
import org.jf.dexlib2.AccessFlags;
|
||||
import org.jf.dexlib2.Format;
|
||||
import org.jf.dexlib2.Opcode;
|
||||
import org.jf.dexlib2.ReferenceType;
|
||||
import org.jf.dexlib2.analysis.AnalysisException;
|
||||
import org.jf.dexlib2.analysis.AnalyzedInstruction;
|
||||
import org.jf.dexlib2.analysis.MethodAnalyzer;
|
||||
import org.jf.dexlib2.dexbacked.DexBackedDexFile.InvalidItemIndex;
|
||||
import org.jf.dexlib2.iface.*;
|
||||
import org.jf.dexlib2.iface.debug.DebugItem;
|
||||
import org.jf.dexlib2.iface.instruction.Instruction;
|
||||
import org.jf.dexlib2.iface.instruction.OffsetInstruction;
|
||||
import org.jf.dexlib2.iface.instruction.ReferenceInstruction;
|
||||
import org.jf.dexlib2.iface.instruction.formats.Instruction31t;
|
||||
import org.jf.dexlib2.iface.reference.MethodReference;
|
||||
import org.jf.dexlib2.immutable.instruction.ImmutableInstruction31t;
|
||||
import org.jf.dexlib2.util.InstructionOffsetMap;
|
||||
import org.jf.dexlib2.util.InstructionOffsetMap.InvalidInstructionOffset;
|
||||
import org.jf.dexlib2.util.ReferenceUtil;
|
||||
import org.jf.dexlib2.util.SyntheticAccessorResolver;
|
||||
import org.jf.dexlib2.util.SyntheticAccessorResolver.AccessedMember;
|
||||
import org.jf.dexlib2.util.TypeUtils;
|
||||
import org.jf.util.ExceptionWithContext;
|
||||
import org.jf.util.IndentingWriter;
|
||||
import org.jf.util.SparseIntArray;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
public class MethodDefinition {
|
||||
@Nonnull public final ClassDefinition classDef;
|
||||
@Nonnull public final Method method;
|
||||
@Nonnull public final MethodImplementation methodImpl;
|
||||
@Nonnull public final ImmutableList<Instruction> instructions;
|
||||
@Nonnull public final List<Instruction> effectiveInstructions;
|
||||
|
||||
@Nonnull public final ImmutableList<MethodParameter> methodParameters;
|
||||
public RegisterFormatter registerFormatter;
|
||||
|
||||
@Nonnull private final LabelCache labelCache = new LabelCache();
|
||||
|
||||
@Nonnull private final SparseIntArray packedSwitchMap;
|
||||
@Nonnull private final SparseIntArray sparseSwitchMap;
|
||||
@Nonnull private final InstructionOffsetMap instructionOffsetMap;
|
||||
|
||||
public MethodDefinition(@Nonnull ClassDefinition classDef, @Nonnull Method method,
|
||||
@Nonnull MethodImplementation methodImpl) {
|
||||
this.classDef = classDef;
|
||||
this.method = method;
|
||||
this.methodImpl = methodImpl;
|
||||
|
||||
try {
|
||||
//TODO: what about try/catch blocks inside the dead code? those will need to be commented out too. ugh.
|
||||
|
||||
instructions = ImmutableList.copyOf(methodImpl.getInstructions());
|
||||
methodParameters = ImmutableList.copyOf(method.getParameters());
|
||||
|
||||
effectiveInstructions = Lists.newArrayList(instructions);
|
||||
|
||||
packedSwitchMap = new SparseIntArray(0);
|
||||
sparseSwitchMap = new SparseIntArray(0);
|
||||
instructionOffsetMap = new InstructionOffsetMap(instructions);
|
||||
|
||||
int endOffset = instructionOffsetMap.getInstructionCodeOffset(instructions.size()-1) +
|
||||
instructions.get(instructions.size()-1).getCodeUnits();
|
||||
|
||||
for (int i=0; i<instructions.size(); i++) {
|
||||
Instruction instruction = instructions.get(i);
|
||||
|
||||
Opcode opcode = instruction.getOpcode();
|
||||
if (opcode == Opcode.PACKED_SWITCH) {
|
||||
boolean valid = true;
|
||||
int codeOffset = instructionOffsetMap.getInstructionCodeOffset(i);
|
||||
int targetOffset = codeOffset + ((OffsetInstruction)instruction).getCodeOffset();
|
||||
try {
|
||||
targetOffset = findPayloadOffset(targetOffset, Opcode.PACKED_SWITCH_PAYLOAD);
|
||||
} catch (InvalidSwitchPayload ex) {
|
||||
valid = false;
|
||||
}
|
||||
if (valid) {
|
||||
if (packedSwitchMap.get(targetOffset, -1) != -1) {
|
||||
Instruction payloadInstruction =
|
||||
findSwitchPayload(targetOffset, Opcode.PACKED_SWITCH_PAYLOAD);
|
||||
targetOffset = endOffset;
|
||||
effectiveInstructions.set(i, new ImmutableInstruction31t(opcode,
|
||||
((Instruction31t)instruction).getRegisterA(), targetOffset-codeOffset));
|
||||
effectiveInstructions.add(payloadInstruction);
|
||||
endOffset += payloadInstruction.getCodeUnits();
|
||||
}
|
||||
packedSwitchMap.append(targetOffset, codeOffset);
|
||||
}
|
||||
} else if (opcode == Opcode.SPARSE_SWITCH) {
|
||||
boolean valid = true;
|
||||
int codeOffset = instructionOffsetMap.getInstructionCodeOffset(i);
|
||||
int targetOffset = codeOffset + ((OffsetInstruction)instruction).getCodeOffset();
|
||||
try {
|
||||
targetOffset = findPayloadOffset(targetOffset, Opcode.SPARSE_SWITCH_PAYLOAD);
|
||||
} catch (InvalidSwitchPayload ex) {
|
||||
valid = false;
|
||||
// The offset to the payload instruction was invalid. Nothing to do, except that we won't
|
||||
// add this instruction to the map.
|
||||
}
|
||||
if (valid) {
|
||||
if (sparseSwitchMap.get(targetOffset, -1) != -1) {
|
||||
Instruction payloadInstruction =
|
||||
findSwitchPayload(targetOffset, Opcode.SPARSE_SWITCH_PAYLOAD);
|
||||
targetOffset = endOffset;
|
||||
effectiveInstructions.set(i, new ImmutableInstruction31t(opcode,
|
||||
((Instruction31t)instruction).getRegisterA(), targetOffset-codeOffset));
|
||||
effectiveInstructions.add(payloadInstruction);
|
||||
endOffset += payloadInstruction.getCodeUnits();
|
||||
}
|
||||
sparseSwitchMap.append(targetOffset, codeOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
String methodString;
|
||||
try {
|
||||
methodString = ReferenceUtil.getMethodDescriptor(method);
|
||||
} catch (Exception ex2) {
|
||||
throw ExceptionWithContext.withContext(ex, "Error while processing method");
|
||||
}
|
||||
throw ExceptionWithContext.withContext(ex, "Error while processing method %s", methodString);
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeEmptyMethodTo(IndentingWriter writer, Method method,
|
||||
baksmaliOptions options) throws IOException {
|
||||
writer.write(".method ");
|
||||
writeAccessFlags(writer, method.getAccessFlags());
|
||||
writer.write(method.getName());
|
||||
writer.write("(");
|
||||
ImmutableList<MethodParameter> methodParameters = ImmutableList.copyOf(method.getParameters());
|
||||
for (MethodParameter parameter: methodParameters) {
|
||||
writer.write(parameter.getType());
|
||||
}
|
||||
writer.write(")");
|
||||
writer.write(method.getReturnType());
|
||||
writer.write('\n');
|
||||
|
||||
writer.indent(4);
|
||||
writeParameters(writer, method, methodParameters, options);
|
||||
|
||||
String containingClass = null;
|
||||
if (options.useImplicitReferences) {
|
||||
containingClass = method.getDefiningClass();
|
||||
}
|
||||
AnnotationFormatter.writeTo(writer, method.getAnnotations(), containingClass);
|
||||
|
||||
writer.deindent(4);
|
||||
writer.write(".end method\n");
|
||||
}
|
||||
|
||||
public void writeTo(IndentingWriter writer) throws IOException {
|
||||
int parameterRegisterCount = 0;
|
||||
if (!AccessFlags.STATIC.isSet(method.getAccessFlags())) {
|
||||
parameterRegisterCount++;
|
||||
}
|
||||
|
||||
writer.write(".method ");
|
||||
writeAccessFlags(writer, method.getAccessFlags());
|
||||
writer.write(method.getName());
|
||||
writer.write("(");
|
||||
for (MethodParameter parameter: methodParameters) {
|
||||
String type = parameter.getType();
|
||||
writer.write(type);
|
||||
parameterRegisterCount++;
|
||||
if (TypeUtils.isWideType(type)) {
|
||||
parameterRegisterCount++;
|
||||
}
|
||||
}
|
||||
writer.write(")");
|
||||
writer.write(method.getReturnType());
|
||||
writer.write('\n');
|
||||
|
||||
writer.indent(4);
|
||||
if (classDef.options.useLocalsDirective) {
|
||||
writer.write(".locals ");
|
||||
writer.printSignedIntAsDec(methodImpl.getRegisterCount() - parameterRegisterCount);
|
||||
} else {
|
||||
writer.write(".registers ");
|
||||
writer.printSignedIntAsDec(methodImpl.getRegisterCount());
|
||||
}
|
||||
writer.write('\n');
|
||||
writeParameters(writer, method, methodParameters, classDef.options);
|
||||
|
||||
if (registerFormatter == null) {
|
||||
registerFormatter = new RegisterFormatter(classDef.options, methodImpl.getRegisterCount(),
|
||||
parameterRegisterCount);
|
||||
}
|
||||
|
||||
String containingClass = null;
|
||||
if (classDef.options.useImplicitReferences) {
|
||||
containingClass = method.getDefiningClass();
|
||||
}
|
||||
AnnotationFormatter.writeTo(writer, method.getAnnotations(), containingClass);
|
||||
|
||||
writer.write('\n');
|
||||
|
||||
List<MethodItem> methodItems = getMethodItems();
|
||||
for (MethodItem methodItem: methodItems) {
|
||||
if (methodItem.writeTo(writer)) {
|
||||
writer.write('\n');
|
||||
}
|
||||
}
|
||||
writer.deindent(4);
|
||||
writer.write(".end method\n");
|
||||
}
|
||||
|
||||
public Instruction findSwitchPayload(int targetOffset, Opcode type) {
|
||||
int targetIndex;
|
||||
try {
|
||||
targetIndex = instructionOffsetMap.getInstructionIndexAtCodeOffset(targetOffset);
|
||||
} catch (InvalidInstructionOffset ex) {
|
||||
throw new InvalidSwitchPayload(targetOffset);
|
||||
}
|
||||
|
||||
//TODO: does dalvik let you pad with multiple nops?
|
||||
//TODO: does dalvik let a switch instruction point to a non-payload instruction?
|
||||
|
||||
Instruction instruction = instructions.get(targetIndex);
|
||||
if (instruction.getOpcode() != type) {
|
||||
// maybe it's pointing to a NOP padding instruction. Look at the next instruction
|
||||
if (instruction.getOpcode() == Opcode.NOP) {
|
||||
targetIndex += 1;
|
||||
if (targetIndex < instructions.size()) {
|
||||
instruction = instructions.get(targetIndex);
|
||||
if (instruction.getOpcode() == type) {
|
||||
return instruction;
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new InvalidSwitchPayload(targetOffset);
|
||||
} else {
|
||||
return instruction;
|
||||
}
|
||||
}
|
||||
|
||||
public int findPayloadOffset(int targetOffset, Opcode type) {
|
||||
int targetIndex;
|
||||
try {
|
||||
targetIndex = instructionOffsetMap.getInstructionIndexAtCodeOffset(targetOffset);
|
||||
} catch (InvalidInstructionOffset ex) {
|
||||
throw new InvalidSwitchPayload(targetOffset);
|
||||
}
|
||||
|
||||
//TODO: does dalvik let you pad with multiple nops?
|
||||
//TODO: does dalvik let a switch instruction point to a non-payload instruction?
|
||||
|
||||
Instruction instruction = instructions.get(targetIndex);
|
||||
if (instruction.getOpcode() != type) {
|
||||
// maybe it's pointing to a NOP padding instruction. Look at the next instruction
|
||||
if (instruction.getOpcode() == Opcode.NOP) {
|
||||
targetIndex += 1;
|
||||
if (targetIndex < instructions.size()) {
|
||||
instruction = instructions.get(targetIndex);
|
||||
if (instruction.getOpcode() == type) {
|
||||
return instructionOffsetMap.getInstructionCodeOffset(targetIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new InvalidSwitchPayload(targetOffset);
|
||||
} else {
|
||||
return targetOffset;
|
||||
}
|
||||
}
|
||||
|
||||
private static void writeAccessFlags(IndentingWriter writer, int accessFlags)
|
||||
throws IOException {
|
||||
for (AccessFlags accessFlag: AccessFlags.getAccessFlagsForMethod(accessFlags)) {
|
||||
writer.write(accessFlag.toString());
|
||||
writer.write(' ');
|
||||
}
|
||||
}
|
||||
|
||||
private static void writeParameters(IndentingWriter writer, Method method,
|
||||
List<? extends MethodParameter> parameters,
|
||||
baksmaliOptions options) throws IOException {
|
||||
boolean isStatic = AccessFlags.STATIC.isSet(method.getAccessFlags());
|
||||
int registerNumber = isStatic?0:1;
|
||||
for (MethodParameter parameter: parameters) {
|
||||
String parameterType = parameter.getType();
|
||||
String parameterName = parameter.getName();
|
||||
Collection<? extends Annotation> annotations = parameter.getAnnotations();
|
||||
if (parameterName != null || annotations.size() != 0) {
|
||||
writer.write(".param p");
|
||||
writer.printSignedIntAsDec(registerNumber);
|
||||
|
||||
if (parameterName != null && options.outputDebugInfo) {
|
||||
writer.write(", ");
|
||||
ReferenceFormatter.writeStringReference(writer, parameterName);
|
||||
}
|
||||
writer.write(" # ");
|
||||
writer.write(parameterType);
|
||||
writer.write("\n");
|
||||
if (annotations.size() > 0) {
|
||||
writer.indent(4);
|
||||
|
||||
String containingClass = null;
|
||||
if (options.useImplicitReferences) {
|
||||
containingClass = method.getDefiningClass();
|
||||
}
|
||||
AnnotationFormatter.writeTo(writer, annotations, containingClass);
|
||||
writer.deindent(4);
|
||||
writer.write(".end param\n");
|
||||
}
|
||||
}
|
||||
|
||||
registerNumber++;
|
||||
if (TypeUtils.isWideType(parameterType)) {
|
||||
registerNumber++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull public LabelCache getLabelCache() {
|
||||
return labelCache;
|
||||
}
|
||||
|
||||
public int getPackedSwitchBaseAddress(int packedSwitchPayloadCodeOffset) {
|
||||
return packedSwitchMap.get(packedSwitchPayloadCodeOffset, -1);
|
||||
}
|
||||
|
||||
public int getSparseSwitchBaseAddress(int sparseSwitchPayloadCodeOffset) {
|
||||
return sparseSwitchMap.get(sparseSwitchPayloadCodeOffset, -1);
|
||||
}
|
||||
|
||||
private List<MethodItem> getMethodItems() {
|
||||
ArrayList<MethodItem> methodItems = new ArrayList<MethodItem>();
|
||||
|
||||
if ((classDef.options.registerInfo != 0) || (classDef.options.deodex && needsAnalyzed())) {
|
||||
addAnalyzedInstructionMethodItems(methodItems);
|
||||
} else {
|
||||
addInstructionMethodItems(methodItems);
|
||||
}
|
||||
|
||||
addTries(methodItems);
|
||||
if (classDef.options.outputDebugInfo) {
|
||||
addDebugInfo(methodItems);
|
||||
}
|
||||
|
||||
if (classDef.options.useSequentialLabels) {
|
||||
setLabelSequentialNumbers();
|
||||
}
|
||||
|
||||
for (LabelMethodItem labelMethodItem: labelCache.getLabels()) {
|
||||
methodItems.add(labelMethodItem);
|
||||
}
|
||||
|
||||
Collections.sort(methodItems);
|
||||
|
||||
return methodItems;
|
||||
}
|
||||
|
||||
private boolean needsAnalyzed() {
|
||||
for (Instruction instruction: methodImpl.getInstructions()) {
|
||||
if (instruction.getOpcode().odexOnly()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void addInstructionMethodItems(List<MethodItem> methodItems) {
|
||||
int currentCodeAddress = 0;
|
||||
|
||||
for (int i=0; i<effectiveInstructions.size(); i++) {
|
||||
Instruction instruction = effectiveInstructions.get(i);
|
||||
|
||||
MethodItem methodItem = InstructionMethodItemFactory.makeInstructionFormatMethodItem(this,
|
||||
currentCodeAddress, instruction);
|
||||
|
||||
methodItems.add(methodItem);
|
||||
|
||||
if (i != effectiveInstructions.size() - 1) {
|
||||
methodItems.add(new BlankMethodItem(currentCodeAddress));
|
||||
}
|
||||
|
||||
if (classDef.options.addCodeOffsets) {
|
||||
methodItems.add(new MethodItem(currentCodeAddress) {
|
||||
|
||||
@Override
|
||||
public double getSortOrder() {
|
||||
return -1000;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean writeTo(IndentingWriter writer) throws IOException {
|
||||
writer.write("#@");
|
||||
writer.printUnsignedLongAsHex(codeAddress & 0xFFFFFFFFL);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (!classDef.options.noAccessorComments && (instruction instanceof ReferenceInstruction)) {
|
||||
Opcode opcode = instruction.getOpcode();
|
||||
|
||||
if (opcode.referenceType == ReferenceType.METHOD) {
|
||||
MethodReference methodReference = null;
|
||||
try {
|
||||
methodReference = (MethodReference)((ReferenceInstruction)instruction).getReference();
|
||||
} catch (InvalidItemIndex ex) {
|
||||
// just ignore it for now. We'll deal with it later, when processing the instructions
|
||||
// themselves
|
||||
}
|
||||
|
||||
if (methodReference != null &&
|
||||
SyntheticAccessorResolver.looksLikeSyntheticAccessor(methodReference.getName())) {
|
||||
AccessedMember accessedMember =
|
||||
classDef.options.syntheticAccessorResolver.getAccessedMember(methodReference);
|
||||
if (accessedMember != null) {
|
||||
methodItems.add(new SyntheticAccessCommentMethodItem(accessedMember, currentCodeAddress));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
currentCodeAddress += instruction.getCodeUnits();
|
||||
}
|
||||
}
|
||||
|
||||
private void addAnalyzedInstructionMethodItems(List<MethodItem> methodItems) {
|
||||
MethodAnalyzer methodAnalyzer = new MethodAnalyzer(classDef.options.classPath, method,
|
||||
classDef.options.inlineResolver);
|
||||
|
||||
AnalysisException analysisException = methodAnalyzer.getAnalysisException();
|
||||
if (analysisException != null) {
|
||||
// TODO: need to keep track of whether any errors occurred, so we can exit with a non-zero result
|
||||
methodItems.add(new CommentMethodItem(
|
||||
String.format("AnalysisException: %s", analysisException.getMessage()),
|
||||
analysisException.codeAddress, Integer.MIN_VALUE));
|
||||
analysisException.printStackTrace(System.err);
|
||||
}
|
||||
|
||||
List<AnalyzedInstruction> instructions = methodAnalyzer.getAnalyzedInstructions();
|
||||
|
||||
int currentCodeAddress = 0;
|
||||
for (int i=0; i<instructions.size(); i++) {
|
||||
AnalyzedInstruction instruction = instructions.get(i);
|
||||
|
||||
MethodItem methodItem = InstructionMethodItemFactory.makeInstructionFormatMethodItem(
|
||||
this, currentCodeAddress, instruction.getInstruction());
|
||||
|
||||
methodItems.add(methodItem);
|
||||
|
||||
if (instruction.getInstruction().getOpcode().format == Format.UnresolvedOdexInstruction) {
|
||||
methodItems.add(new CommentedOutMethodItem(
|
||||
InstructionMethodItemFactory.makeInstructionFormatMethodItem(
|
||||
this, currentCodeAddress, instruction.getOriginalInstruction())));
|
||||
}
|
||||
|
||||
if (i != instructions.size() - 1) {
|
||||
methodItems.add(new BlankMethodItem(currentCodeAddress));
|
||||
}
|
||||
|
||||
if (classDef.options.addCodeOffsets) {
|
||||
methodItems.add(new MethodItem(currentCodeAddress) {
|
||||
|
||||
@Override
|
||||
public double getSortOrder() {
|
||||
return -1000;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean writeTo(IndentingWriter writer) throws IOException {
|
||||
writer.write("#@");
|
||||
writer.printUnsignedLongAsHex(codeAddress & 0xFFFFFFFFL);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (classDef.options.registerInfo != 0 &&
|
||||
!instruction.getInstruction().getOpcode().format.isPayloadFormat) {
|
||||
methodItems.add(
|
||||
new PreInstructionRegisterInfoMethodItem(classDef.options.registerInfo,
|
||||
methodAnalyzer, registerFormatter, instruction, currentCodeAddress));
|
||||
|
||||
methodItems.add(
|
||||
new PostInstructionRegisterInfoMethodItem(registerFormatter, instruction, currentCodeAddress));
|
||||
}
|
||||
|
||||
currentCodeAddress += instruction.getInstruction().getCodeUnits();
|
||||
}
|
||||
}
|
||||
|
||||
private void addTries(List<MethodItem> methodItems) {
|
||||
List<? extends TryBlock<? extends ExceptionHandler>> tryBlocks = methodImpl.getTryBlocks();
|
||||
if (tryBlocks.size() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int lastInstructionAddress = instructionOffsetMap.getInstructionCodeOffset(instructions.size() - 1);
|
||||
int codeSize = lastInstructionAddress + instructions.get(instructions.size() - 1).getCodeUnits();
|
||||
|
||||
for (TryBlock<? extends ExceptionHandler> tryBlock: tryBlocks) {
|
||||
int startAddress = tryBlock.getStartCodeAddress();
|
||||
int endAddress = startAddress + tryBlock.getCodeUnitCount();
|
||||
|
||||
if (startAddress >= codeSize) {
|
||||
throw new RuntimeException(String.format("Try start offset %d is past the end of the code block.",
|
||||
startAddress));
|
||||
}
|
||||
// Note: not >=. endAddress == codeSize is valid, when the try covers the last instruction
|
||||
if (endAddress > codeSize) {
|
||||
throw new RuntimeException(String.format("Try end offset %d is past the end of the code block.",
|
||||
endAddress));
|
||||
}
|
||||
|
||||
/**
|
||||
* The end address points to the address immediately after the end of the last
|
||||
* instruction that the try block covers. We want the .catch directive and end_try
|
||||
* label to be associated with the last covered instruction, so we need to get
|
||||
* the address for that instruction
|
||||
*/
|
||||
|
||||
int lastCoveredIndex = instructionOffsetMap.getInstructionIndexAtCodeOffset(endAddress - 1, false);
|
||||
int lastCoveredAddress = instructionOffsetMap.getInstructionCodeOffset(lastCoveredIndex);
|
||||
|
||||
for (ExceptionHandler handler: tryBlock.getExceptionHandlers()) {
|
||||
int handlerAddress = handler.getHandlerCodeAddress();
|
||||
if (handlerAddress >= codeSize) {
|
||||
throw new ExceptionWithContext(
|
||||
"Exception handler offset %d is past the end of the code block.", handlerAddress);
|
||||
}
|
||||
|
||||
//use the address from the last covered instruction
|
||||
CatchMethodItem catchMethodItem = new CatchMethodItem(classDef.options, labelCache, lastCoveredAddress,
|
||||
handler.getExceptionType(), startAddress, endAddress, handlerAddress);
|
||||
methodItems.add(catchMethodItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addDebugInfo(final List<MethodItem> methodItems) {
|
||||
for (DebugItem debugItem: methodImpl.getDebugItems()) {
|
||||
methodItems.add(DebugMethodItem.build(registerFormatter, debugItem));
|
||||
}
|
||||
}
|
||||
|
||||
private void setLabelSequentialNumbers() {
|
||||
HashMap<String, Integer> nextLabelSequenceByType = new HashMap<String, Integer>();
|
||||
ArrayList<LabelMethodItem> sortedLabels = new ArrayList<LabelMethodItem>(labelCache.getLabels());
|
||||
|
||||
//sort the labels by their location in the method
|
||||
Collections.sort(sortedLabels);
|
||||
|
||||
for (LabelMethodItem labelMethodItem: sortedLabels) {
|
||||
Integer labelSequence = nextLabelSequenceByType.get(labelMethodItem.getLabelPrefix());
|
||||
if (labelSequence == null) {
|
||||
labelSequence = 0;
|
||||
}
|
||||
labelMethodItem.setLabelSequence(labelSequence);
|
||||
nextLabelSequenceByType.put(labelMethodItem.getLabelPrefix(), labelSequence + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private String getContainingClassForImplicitReference() {
|
||||
if (classDef.options.useImplicitReferences) {
|
||||
return classDef.classDef.getType();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static class LabelCache {
|
||||
protected HashMap<LabelMethodItem, LabelMethodItem> labels = new HashMap<LabelMethodItem, LabelMethodItem>();
|
||||
|
||||
public LabelCache() {
|
||||
}
|
||||
|
||||
public LabelMethodItem internLabel(LabelMethodItem labelMethodItem) {
|
||||
LabelMethodItem internedLabelMethodItem = labels.get(labelMethodItem);
|
||||
if (internedLabelMethodItem != null) {
|
||||
return internedLabelMethodItem;
|
||||
}
|
||||
labels.put(labelMethodItem, labelMethodItem);
|
||||
return labelMethodItem;
|
||||
}
|
||||
|
||||
|
||||
public Collection<LabelMethodItem> getLabels() {
|
||||
return labels.values();
|
||||
}
|
||||
}
|
||||
|
||||
public static class InvalidSwitchPayload extends ExceptionWithContext {
|
||||
private final int payloadOffset;
|
||||
|
||||
public InvalidSwitchPayload(int payloadOffset) {
|
||||
super("No switch payload at offset: %d", payloadOffset);
|
||||
this.payloadOffset = payloadOffset;
|
||||
}
|
||||
|
||||
public int getPayloadOffset() {
|
||||
return payloadOffset;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 Ben Gruver (JesusFreke)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali.Adaptors;
|
||||
|
||||
import org.jf.util.IndentingWriter;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public abstract class MethodItem implements Comparable<MethodItem> {
|
||||
protected final int codeAddress;
|
||||
|
||||
protected MethodItem(int codeAddress) {
|
||||
this.codeAddress = codeAddress;
|
||||
}
|
||||
|
||||
public int getCodeAddress() {
|
||||
return codeAddress;
|
||||
}
|
||||
|
||||
//return an arbitrary double that determines how this item will be sorted with others at the same address
|
||||
public abstract double getSortOrder();
|
||||
|
||||
public int compareTo(MethodItem methodItem) {
|
||||
int result = ((Integer) codeAddress).compareTo(methodItem.codeAddress);
|
||||
|
||||
if (result == 0){
|
||||
return ((Double)getSortOrder()).compareTo(methodItem.getSortOrder());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public abstract boolean writeTo(IndentingWriter writer) throws IOException;
|
||||
}
|
@ -1,102 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 Ben Gruver
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali.Adaptors;
|
||||
|
||||
import org.jf.baksmali.baksmaliOptions;
|
||||
import org.jf.dexlib2.analysis.AnalyzedInstruction;
|
||||
import org.jf.dexlib2.analysis.RegisterType;
|
||||
import org.jf.util.IndentingWriter;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.io.IOException;
|
||||
import java.util.BitSet;
|
||||
|
||||
public class PostInstructionRegisterInfoMethodItem extends MethodItem {
|
||||
@Nonnull private final RegisterFormatter registerFormatter;
|
||||
@Nonnull private final AnalyzedInstruction analyzedInstruction;
|
||||
|
||||
public PostInstructionRegisterInfoMethodItem(@Nonnull RegisterFormatter registerFormatter,
|
||||
@Nonnull AnalyzedInstruction analyzedInstruction,
|
||||
int codeAddress) {
|
||||
super(codeAddress);
|
||||
this.registerFormatter = registerFormatter;
|
||||
this.analyzedInstruction = analyzedInstruction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getSortOrder() {
|
||||
return 100.1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean writeTo(IndentingWriter writer) throws IOException {
|
||||
int registerInfo = registerFormatter.options.registerInfo;
|
||||
int registerCount = analyzedInstruction.getRegisterCount();
|
||||
BitSet registers = new BitSet(registerCount);
|
||||
|
||||
if ((registerInfo & baksmaliOptions.ALL) != 0) {
|
||||
registers.set(0, registerCount);
|
||||
} else {
|
||||
if ((registerInfo & baksmaliOptions.ALLPOST) != 0) {
|
||||
registers.set(0, registerCount);
|
||||
} else if ((registerInfo & baksmaliOptions.DEST) != 0) {
|
||||
addDestRegs(registers, registerCount);
|
||||
}
|
||||
}
|
||||
|
||||
return writeRegisterInfo(writer, registers);
|
||||
}
|
||||
|
||||
private void addDestRegs(BitSet printPostRegister, int registerCount) {
|
||||
for (int registerNum=0; registerNum<registerCount; registerNum++) {
|
||||
if (!analyzedInstruction.getPreInstructionRegisterType(registerNum).equals(
|
||||
analyzedInstruction.getPostInstructionRegisterType(registerNum))) {
|
||||
printPostRegister.set(registerNum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean writeRegisterInfo(IndentingWriter writer, BitSet registers) throws IOException {
|
||||
int registerNum = registers.nextSetBit(0);
|
||||
if (registerNum < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
writer.write('#');
|
||||
for (; registerNum >= 0; registerNum = registers.nextSetBit(registerNum + 1)) {
|
||||
RegisterType registerType = analyzedInstruction.getPostInstructionRegisterType(registerNum);
|
||||
|
||||
registerFormatter.writeTo(writer, registerNum);
|
||||
writer.write('=');
|
||||
registerType.writeTo(writer);
|
||||
writer.write(';');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,260 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 Ben Gruver
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali.Adaptors;
|
||||
|
||||
import org.jf.baksmali.baksmaliOptions;
|
||||
import org.jf.dexlib2.analysis.AnalyzedInstruction;
|
||||
import org.jf.dexlib2.analysis.MethodAnalyzer;
|
||||
import org.jf.dexlib2.analysis.RegisterType;
|
||||
import org.jf.dexlib2.iface.instruction.*;
|
||||
import org.jf.util.IndentingWriter;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.io.IOException;
|
||||
import java.util.BitSet;
|
||||
|
||||
public class PreInstructionRegisterInfoMethodItem extends MethodItem {
|
||||
private static AnalyzedInstruction lastInstruction;
|
||||
|
||||
private final int registerInfo;
|
||||
@Nonnull private final MethodAnalyzer methodAnalyzer;
|
||||
@Nonnull private final RegisterFormatter registerFormatter;
|
||||
@Nonnull private final AnalyzedInstruction analyzedInstruction;
|
||||
|
||||
public PreInstructionRegisterInfoMethodItem(int registerInfo,
|
||||
@Nonnull MethodAnalyzer methodAnalyzer,
|
||||
@Nonnull RegisterFormatter registerFormatter,
|
||||
@Nonnull AnalyzedInstruction analyzedInstruction,
|
||||
int codeAddress) {
|
||||
super(codeAddress);
|
||||
this.registerInfo = registerInfo;
|
||||
this.methodAnalyzer = methodAnalyzer;
|
||||
this.registerFormatter = registerFormatter;
|
||||
this.analyzedInstruction = analyzedInstruction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getSortOrder() {
|
||||
return 99.9;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean writeTo(IndentingWriter writer) throws IOException {
|
||||
int registerCount = analyzedInstruction.getRegisterCount();
|
||||
BitSet registers = new BitSet(registerCount);
|
||||
BitSet mergeRegisters = null;
|
||||
|
||||
if ((registerInfo & baksmaliOptions.ALL) != 0) {
|
||||
registers.set(0, registerCount);
|
||||
} else {
|
||||
if ((registerInfo & baksmaliOptions.ALLPRE) != 0) {
|
||||
registers.set(0, registerCount);
|
||||
} else {
|
||||
if ((registerInfo & baksmaliOptions.ARGS) != 0) {
|
||||
addArgsRegs(registers);
|
||||
}
|
||||
if ((registerInfo & baksmaliOptions.DIFFPRE) != 0) {
|
||||
addDiffRegs(registers);
|
||||
}
|
||||
if ((registerInfo & baksmaliOptions.MERGE) != 0) {
|
||||
if (analyzedInstruction.isBeginningInstruction()) {
|
||||
addParamRegs(registers, registerCount);
|
||||
}
|
||||
mergeRegisters = new BitSet(registerCount);
|
||||
addMergeRegs(mergeRegisters, registerCount);
|
||||
} else if ((registerInfo & baksmaliOptions.FULLMERGE) != 0 &&
|
||||
(analyzedInstruction.isBeginningInstruction())) {
|
||||
addParamRegs(registers, registerCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((registerInfo & baksmaliOptions.FULLMERGE) != 0) {
|
||||
if (mergeRegisters == null) {
|
||||
mergeRegisters = new BitSet(registerCount);
|
||||
addMergeRegs(mergeRegisters, registerCount);
|
||||
}
|
||||
registers.or(mergeRegisters);
|
||||
} else if (mergeRegisters != null) {
|
||||
registers.or(mergeRegisters);
|
||||
mergeRegisters = null;
|
||||
}
|
||||
|
||||
return writeRegisterInfo(writer, registers, mergeRegisters);
|
||||
}
|
||||
|
||||
private void addArgsRegs(BitSet registers) {
|
||||
if (analyzedInstruction.getInstruction() instanceof RegisterRangeInstruction) {
|
||||
RegisterRangeInstruction instruction = (RegisterRangeInstruction)analyzedInstruction.getInstruction();
|
||||
|
||||
registers.set(instruction.getStartRegister(),
|
||||
instruction.getStartRegister() + instruction.getRegisterCount());
|
||||
} else if (analyzedInstruction.getInstruction() instanceof FiveRegisterInstruction) {
|
||||
FiveRegisterInstruction instruction = (FiveRegisterInstruction)analyzedInstruction.getInstruction();
|
||||
int regCount = instruction.getRegisterCount();
|
||||
switch (regCount) {
|
||||
case 5:
|
||||
registers.set(instruction.getRegisterG());
|
||||
//fall through
|
||||
case 4:
|
||||
registers.set(instruction.getRegisterF());
|
||||
//fall through
|
||||
case 3:
|
||||
registers.set(instruction.getRegisterE());
|
||||
//fall through
|
||||
case 2:
|
||||
registers.set(instruction.getRegisterD());
|
||||
//fall through
|
||||
case 1:
|
||||
registers.set(instruction.getRegisterC());
|
||||
}
|
||||
} else if (analyzedInstruction.getInstruction() instanceof ThreeRegisterInstruction) {
|
||||
ThreeRegisterInstruction instruction = (ThreeRegisterInstruction)analyzedInstruction.getInstruction();
|
||||
registers.set(instruction.getRegisterA());
|
||||
registers.set(instruction.getRegisterB());
|
||||
registers.set(instruction.getRegisterC());
|
||||
} else if (analyzedInstruction.getInstruction() instanceof TwoRegisterInstruction) {
|
||||
TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.getInstruction();
|
||||
registers.set(instruction.getRegisterA());
|
||||
registers.set(instruction.getRegisterB());
|
||||
} else if (analyzedInstruction.getInstruction() instanceof OneRegisterInstruction) {
|
||||
OneRegisterInstruction instruction = (OneRegisterInstruction)analyzedInstruction.getInstruction();
|
||||
registers.set(instruction.getRegisterA());
|
||||
}
|
||||
}
|
||||
|
||||
private void addDiffRegs(BitSet registers) {
|
||||
if (! analyzedInstruction.isBeginningInstruction()) {
|
||||
for (int i = 0; i < analyzedInstruction.getRegisterCount(); i++) {
|
||||
if (lastInstruction.getPreInstructionRegisterType(i).category !=
|
||||
analyzedInstruction.getPreInstructionRegisterType(i).category) {
|
||||
registers.set(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lastInstruction = analyzedInstruction;
|
||||
}
|
||||
|
||||
private void addMergeRegs(BitSet registers, int registerCount) {
|
||||
if (analyzedInstruction.getPredecessorCount() <= 1) {
|
||||
//in the common case of an instruction that only has a single predecessor which is the previous
|
||||
//instruction, the pre-instruction registers will always match the previous instruction's
|
||||
//post-instruction registers
|
||||
return;
|
||||
}
|
||||
|
||||
for (int registerNum=0; registerNum<registerCount; registerNum++) {
|
||||
RegisterType mergedRegisterType = analyzedInstruction.getPreInstructionRegisterType(registerNum);
|
||||
|
||||
for (AnalyzedInstruction predecessor: analyzedInstruction.getPredecessors()) {
|
||||
RegisterType predecessorRegisterType = predecessor.getPostInstructionRegisterType(registerNum);
|
||||
if (predecessorRegisterType.category != RegisterType.UNKNOWN &&
|
||||
!predecessorRegisterType.equals(mergedRegisterType)) {
|
||||
registers.set(registerNum);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addParamRegs(BitSet registers, int registerCount) {
|
||||
int parameterRegisterCount = methodAnalyzer.getParamRegisterCount();
|
||||
registers.set(registerCount-parameterRegisterCount, registerCount);
|
||||
}
|
||||
|
||||
private void writeFullMerge(IndentingWriter writer, int registerNum) throws IOException {
|
||||
registerFormatter.writeTo(writer, registerNum);
|
||||
writer.write('=');
|
||||
analyzedInstruction.getPreInstructionRegisterType(registerNum).writeTo(writer);
|
||||
writer.write(":merge{");
|
||||
|
||||
boolean first = true;
|
||||
|
||||
for (AnalyzedInstruction predecessor: analyzedInstruction.getPredecessors()) {
|
||||
RegisterType predecessorRegisterType = predecessor.getPostInstructionRegisterType(registerNum);
|
||||
|
||||
if (!first) {
|
||||
writer.write(',');
|
||||
}
|
||||
|
||||
if (predecessor.getInstructionIndex() == -1) {
|
||||
//the fake "StartOfMethod" instruction
|
||||
writer.write("Start:");
|
||||
} else {
|
||||
writer.write("0x");
|
||||
writer.printUnsignedLongAsHex(methodAnalyzer.getInstructionAddress(predecessor));
|
||||
writer.write(':');
|
||||
}
|
||||
predecessorRegisterType.writeTo(writer);
|
||||
|
||||
first = false;
|
||||
}
|
||||
writer.write('}');
|
||||
}
|
||||
|
||||
private boolean writeRegisterInfo(IndentingWriter writer, BitSet registers,
|
||||
BitSet fullMergeRegisters) throws IOException {
|
||||
boolean firstRegister = true;
|
||||
boolean previousWasFullMerge = false;
|
||||
int registerNum = registers.nextSetBit(0);
|
||||
if (registerNum < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
writer.write('#');
|
||||
for (; registerNum >= 0; registerNum = registers.nextSetBit(registerNum + 1)) {
|
||||
boolean fullMerge = fullMergeRegisters!=null && fullMergeRegisters.get(registerNum);
|
||||
if (fullMerge) {
|
||||
if (!firstRegister) {
|
||||
writer.write('\n');
|
||||
writer.write('#');
|
||||
}
|
||||
writeFullMerge(writer, registerNum);
|
||||
previousWasFullMerge = true;
|
||||
} else {
|
||||
if (previousWasFullMerge) {
|
||||
writer.write('\n');
|
||||
writer.write('#');
|
||||
previousWasFullMerge = false;
|
||||
}
|
||||
|
||||
RegisterType registerType = analyzedInstruction.getPreInstructionRegisterType(registerNum);
|
||||
|
||||
registerFormatter.writeTo(writer, registerNum);
|
||||
writer.write('=');
|
||||
|
||||
registerType.writeTo(writer);
|
||||
writer.write(';');
|
||||
}
|
||||
|
||||
firstRegister = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 Ben Gruver
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali.Adaptors;
|
||||
|
||||
import org.jf.dexlib2.ReferenceType;
|
||||
import org.jf.dexlib2.iface.reference.*;
|
||||
import org.jf.dexlib2.util.ReferenceUtil;
|
||||
import org.jf.util.IndentingWriter;
|
||||
import org.jf.util.StringUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class ReferenceFormatter {
|
||||
public static void writeStringReference(IndentingWriter writer, String item) throws IOException {
|
||||
writer.write('"');
|
||||
StringUtils.writeEscapedString(writer, item);
|
||||
writer.write('"');
|
||||
}
|
||||
|
||||
public static void writeReference(IndentingWriter writer, int referenceType,
|
||||
Reference reference) throws IOException {
|
||||
switch (referenceType) {
|
||||
case ReferenceType.STRING:
|
||||
writeStringReference(writer, ((StringReference)reference).getString());
|
||||
return;
|
||||
case ReferenceType.TYPE:
|
||||
writer.write(((TypeReference)reference).getType());
|
||||
return;
|
||||
case ReferenceType.METHOD:
|
||||
ReferenceUtil.writeMethodDescriptor(writer, (MethodReference)reference);
|
||||
return;
|
||||
case ReferenceType.FIELD:
|
||||
ReferenceUtil.writeFieldDescriptor(writer, (FieldReference)reference);
|
||||
return;
|
||||
default:
|
||||
throw new IllegalStateException("Unknown reference type");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,99 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 Ben Gruver (JesusFreke)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali.Adaptors;
|
||||
|
||||
import org.jf.baksmali.baksmaliOptions;
|
||||
import org.jf.util.IndentingWriter;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* This class contains the logic used for formatting registers
|
||||
*/
|
||||
public class RegisterFormatter {
|
||||
@Nonnull public final baksmaliOptions options;
|
||||
public final int registerCount;
|
||||
public final int parameterRegisterCount;
|
||||
|
||||
public RegisterFormatter(@Nonnull baksmaliOptions options, int registerCount, int parameterRegisterCount) {
|
||||
this.options = options;
|
||||
this.registerCount = registerCount;
|
||||
this.parameterRegisterCount = parameterRegisterCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write out the register range value used by Format3rc. If baksmali.noParameterRegisters is true, it will always
|
||||
* output the registers in the v<n> format. But if false, then it will check if *both* registers are parameter
|
||||
* registers, and if so, use the p<n> format for both. If only the last register is a parameter register, it will
|
||||
* use the v<n> format for both, otherwise it would be confusing to have something like {v20 .. p1}
|
||||
* @param writer the <code>IndentingWriter</code> to write to
|
||||
* @param startRegister the first register in the range
|
||||
* @param lastRegister the last register in the range
|
||||
*/
|
||||
public void writeRegisterRange(IndentingWriter writer, int startRegister, int lastRegister) throws IOException {
|
||||
if (!options.noParameterRegisters) {
|
||||
assert startRegister <= lastRegister;
|
||||
|
||||
if (startRegister >= registerCount - parameterRegisterCount) {
|
||||
writer.write("{p");
|
||||
writer.printSignedIntAsDec(startRegister - (registerCount - parameterRegisterCount));
|
||||
writer.write(" .. p");
|
||||
writer.printSignedIntAsDec(lastRegister - (registerCount - parameterRegisterCount));
|
||||
writer.write('}');
|
||||
return;
|
||||
}
|
||||
}
|
||||
writer.write("{v");
|
||||
writer.printSignedIntAsDec(startRegister);
|
||||
writer.write(" .. v");
|
||||
writer.printSignedIntAsDec(lastRegister);
|
||||
writer.write('}');
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a register with the appropriate format. If baksmali.noParameterRegisters is true, then it will always
|
||||
* output a register in the v<n> format. If false, then it determines if the register is a parameter register,
|
||||
* and if so, formats it in the p<n> format instead.
|
||||
*
|
||||
* @param writer the <code>IndentingWriter</code> to write to
|
||||
* @param register the register number
|
||||
*/
|
||||
public void writeTo(IndentingWriter writer, int register) throws IOException {
|
||||
if (!options.noParameterRegisters) {
|
||||
if (register >= registerCount - parameterRegisterCount) {
|
||||
writer.write('p');
|
||||
writer.printSignedIntAsDec((register - (registerCount - parameterRegisterCount)));
|
||||
return;
|
||||
}
|
||||
}
|
||||
writer.write('v');
|
||||
writer.printSignedIntAsDec(register);
|
||||
}
|
||||
}
|
@ -1,121 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2011 Ben Gruver
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali.Adaptors;
|
||||
|
||||
import org.jf.dexlib2.ReferenceType;
|
||||
import org.jf.dexlib2.util.SyntheticAccessorResolver;
|
||||
import org.jf.util.ExceptionWithContext;
|
||||
import org.jf.util.IndentingWriter;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class SyntheticAccessCommentMethodItem extends MethodItem {
|
||||
private final SyntheticAccessorResolver.AccessedMember accessedMember;
|
||||
|
||||
public SyntheticAccessCommentMethodItem(SyntheticAccessorResolver.AccessedMember accessedMember, int codeAddress) {
|
||||
super(codeAddress);
|
||||
this.accessedMember = accessedMember;
|
||||
}
|
||||
|
||||
public double getSortOrder() {
|
||||
//just before the pre-instruction register information, if any
|
||||
return 99.8;
|
||||
}
|
||||
|
||||
public boolean writeTo(IndentingWriter writer) throws IOException {
|
||||
writer.write("# ");
|
||||
switch (accessedMember.accessedMemberType) {
|
||||
case SyntheticAccessorResolver.METHOD:
|
||||
writer.write("invokes: ");
|
||||
break;
|
||||
case SyntheticAccessorResolver.GETTER:
|
||||
writer.write("getter for: ");
|
||||
break;
|
||||
case SyntheticAccessorResolver.SETTER:
|
||||
writer.write("setter for: ");
|
||||
break;
|
||||
case SyntheticAccessorResolver.PREFIX_INCREMENT:
|
||||
writer.write("++operator for: ");
|
||||
break;
|
||||
case SyntheticAccessorResolver.POSTFIX_INCREMENT:
|
||||
writer.write("operator++ for: ");
|
||||
break;
|
||||
case SyntheticAccessorResolver.PREFIX_DECREMENT:
|
||||
writer.write("--operator for: ");
|
||||
break;
|
||||
case SyntheticAccessorResolver.POSTFIX_DECREMENT:
|
||||
writer.write("operator-- for: ");
|
||||
break;
|
||||
case SyntheticAccessorResolver.ADD_ASSIGNMENT:
|
||||
writer.write("+= operator for: ");
|
||||
break;
|
||||
case SyntheticAccessorResolver.SUB_ASSIGNMENT:
|
||||
writer.write("-= operator for: ");
|
||||
break;
|
||||
case SyntheticAccessorResolver.MUL_ASSIGNMENT:
|
||||
writer.write("*= operator for: ");
|
||||
break;
|
||||
case SyntheticAccessorResolver.DIV_ASSIGNMENT:
|
||||
writer.write("/= operator for: ");
|
||||
break;
|
||||
case SyntheticAccessorResolver.REM_ASSIGNMENT:
|
||||
writer.write("%= operator for: ");
|
||||
break;
|
||||
case SyntheticAccessorResolver.AND_ASSIGNMENT:
|
||||
writer.write("&= operator for: ");
|
||||
break;
|
||||
case SyntheticAccessorResolver.OR_ASSIGNMENT:
|
||||
writer.write("|= operator for: ");
|
||||
break;
|
||||
case SyntheticAccessorResolver.XOR_ASSIGNMENT:
|
||||
writer.write("^= operator for: ");
|
||||
break;
|
||||
case SyntheticAccessorResolver.SHL_ASSIGNMENT:
|
||||
writer.write("<<= operator for: ");
|
||||
break;
|
||||
case SyntheticAccessorResolver.SHR_ASSIGNMENT:
|
||||
writer.write(">>= operator for: ");
|
||||
break;
|
||||
case SyntheticAccessorResolver.USHR_ASSIGNMENT:
|
||||
writer.write(">>>= operator for: ");
|
||||
break;
|
||||
default:
|
||||
throw new ExceptionWithContext("Unknown access type: %d", accessedMember.accessedMemberType);
|
||||
}
|
||||
|
||||
int referenceType;
|
||||
if (accessedMember.accessedMemberType == SyntheticAccessorResolver.METHOD) {
|
||||
referenceType = ReferenceType.METHOD;
|
||||
} else {
|
||||
referenceType = ReferenceType.FIELD;
|
||||
}
|
||||
ReferenceFormatter.writeReference(writer, referenceType, accessedMember.accessedMember);
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 Ben Gruver
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali.Renderers;
|
||||
|
||||
import org.jf.util.IndentingWriter;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class BooleanRenderer {
|
||||
public static void writeTo(IndentingWriter writer, boolean val) throws IOException {
|
||||
if (val) {
|
||||
writer.write("true");
|
||||
} else {
|
||||
writer.write("false");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 Ben Gruver (JesusFreke)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali.Renderers;
|
||||
|
||||
import org.jf.util.IndentingWriter;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class ByteRenderer {
|
||||
public static void writeTo(IndentingWriter writer, byte val) throws IOException {
|
||||
if (val<0) {
|
||||
writer.write("-0x");
|
||||
writer.printUnsignedLongAsHex(-val);
|
||||
writer.write('t');
|
||||
} else {
|
||||
writer.write("0x");
|
||||
writer.printUnsignedLongAsHex(val);
|
||||
writer.write('t');
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeUnsignedTo(IndentingWriter writer, byte val) throws IOException {
|
||||
writer.write("0x");
|
||||
writer.printUnsignedLongAsHex(val & 0xFF);
|
||||
writer.write('t');
|
||||
}
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 Ben Gruver (JesusFreke)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali.Renderers;
|
||||
|
||||
import org.jf.util.IndentingWriter;
|
||||
import org.jf.util.StringUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class CharRenderer {
|
||||
public static void writeTo(IndentingWriter writer, char val) throws IOException {
|
||||
writer.write('\'');
|
||||
StringUtils.writeEscapedChar(writer, val);
|
||||
writer.write('\'');
|
||||
}
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 Ben Gruver
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali.Renderers;
|
||||
|
||||
import org.jf.util.IndentingWriter;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class DoubleRenderer {
|
||||
public static void writeTo(IndentingWriter writer, double val) throws IOException {
|
||||
writer.write(Double.toString(val));
|
||||
}
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 Ben Gruver (JesusFreke)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali.Renderers;
|
||||
|
||||
import org.jf.util.IndentingWriter;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class FloatRenderer {
|
||||
public static void writeTo(IndentingWriter writer, float val) throws IOException {
|
||||
writer.write(Float.toString(val));
|
||||
writer.write('f');
|
||||
}
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 Ben Gruver (JesusFreke)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali.Renderers;
|
||||
|
||||
import org.jf.util.IndentingWriter;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class IntegerRenderer {
|
||||
public static void writeTo(IndentingWriter writer, int val) throws IOException {
|
||||
if (val<0) {
|
||||
writer.write("-0x");
|
||||
writer.printUnsignedLongAsHex(-((long) val));
|
||||
} else {
|
||||
writer.write("0x");
|
||||
writer.printUnsignedLongAsHex(val);
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeUnsignedTo(IndentingWriter writer, int val) throws IOException {
|
||||
writer.write("0x");
|
||||
writer.printUnsignedLongAsHex(val & 0xFFFFFFFFL);
|
||||
}
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 Ben Gruver (JesusFreke)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali.Renderers;
|
||||
|
||||
import org.jf.util.IndentingWriter;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class LongRenderer {
|
||||
public static void writeTo(IndentingWriter writer, long val) throws IOException {
|
||||
if (val<0) {
|
||||
writer.write("-0x");
|
||||
writer.printUnsignedLongAsHex(-val);
|
||||
writer.write('L');
|
||||
} else {
|
||||
writer.write("0x");
|
||||
writer.printUnsignedLongAsHex(val);
|
||||
writer.write('L');
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeSignedIntOrLongTo(IndentingWriter writer, long val) throws IOException {
|
||||
if (val<0) {
|
||||
writer.write("-0x");
|
||||
writer.printUnsignedLongAsHex(-val);
|
||||
if (val < Integer.MIN_VALUE) {
|
||||
writer.write('L');
|
||||
}
|
||||
} else {
|
||||
writer.write("0x");
|
||||
writer.printUnsignedLongAsHex(val);
|
||||
if (val > Integer.MAX_VALUE) {
|
||||
writer.write('L');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 Ben Gruver (JesusFreke)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali.Renderers;
|
||||
|
||||
import org.jf.util.IndentingWriter;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class ShortRenderer {
|
||||
public static void writeTo(IndentingWriter writer, short val) throws IOException {
|
||||
if (val < 0) {
|
||||
writer.write("-0x");
|
||||
writer.printUnsignedLongAsHex(-val);
|
||||
writer.write('s');
|
||||
} else {
|
||||
writer.write("0x");
|
||||
writer.printUnsignedLongAsHex(val);
|
||||
writer.write('s');
|
||||
}
|
||||
}
|
||||
}
|
@ -1,247 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 Ben Gruver (JesusFreke)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Ordering;
|
||||
import org.jf.baksmali.Adaptors.ClassDefinition;
|
||||
import org.jf.dexlib2.analysis.ClassPath;
|
||||
import org.jf.dexlib2.analysis.CustomInlineMethodResolver;
|
||||
import org.jf.dexlib2.iface.ClassDef;
|
||||
import org.jf.dexlib2.iface.DexFile;
|
||||
import org.jf.dexlib2.util.SyntheticAccessorResolver;
|
||||
import org.jf.util.ClassFileNameHandler;
|
||||
import org.jf.util.IndentingWriter;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.helpers.DefaultHandler;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
import javax.xml.parsers.SAXParser;
|
||||
import javax.xml.parsers.SAXParserFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
public class baksmali {
|
||||
|
||||
public static boolean disassembleDexFile(DexFile dexFile, final baksmaliOptions options) {
|
||||
if (options.registerInfo != 0 || options.deodex) {
|
||||
try {
|
||||
Iterable<String> extraClassPathEntries;
|
||||
if (options.extraClassPathEntries != null) {
|
||||
extraClassPathEntries = options.extraClassPathEntries;
|
||||
} else {
|
||||
extraClassPathEntries = ImmutableList.of();
|
||||
}
|
||||
|
||||
options.classPath = ClassPath.fromClassPath(options.bootClassPathDirs,
|
||||
Iterables.concat(options.bootClassPathEntries, extraClassPathEntries), dexFile,
|
||||
options.apiLevel, options.checkPackagePrivateAccess, options.experimental);
|
||||
|
||||
if (options.customInlineDefinitions != null) {
|
||||
options.inlineResolver = new CustomInlineMethodResolver(options.classPath,
|
||||
options.customInlineDefinitions);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
System.err.println("\n\nError occurred while loading boot class path files. Aborting.");
|
||||
ex.printStackTrace(System.err);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (options.resourceIdFileEntries != null) {
|
||||
class PublicHandler extends DefaultHandler {
|
||||
String prefix = null;
|
||||
public PublicHandler(String prefix) {
|
||||
super();
|
||||
this.prefix = prefix;
|
||||
}
|
||||
|
||||
public void startElement(String uri, String localName,
|
||||
String qName, Attributes attr) throws SAXException {
|
||||
if (qName.equals("public")) {
|
||||
String type = attr.getValue("type");
|
||||
String name = attr.getValue("name").replace('.', '_');
|
||||
Integer public_key = Integer.decode(attr.getValue("id"));
|
||||
String public_val = new StringBuffer()
|
||||
.append(prefix)
|
||||
.append(".")
|
||||
.append(type)
|
||||
.append(".")
|
||||
.append(name)
|
||||
.toString();
|
||||
options.resourceIds.put(public_key, public_val);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
for (Entry<String,String> entry: options.resourceIdFileEntries.entrySet()) {
|
||||
try {
|
||||
SAXParser saxp = SAXParserFactory.newInstance().newSAXParser();
|
||||
String prefix = entry.getValue();
|
||||
saxp.parse(entry.getKey(), new PublicHandler(prefix));
|
||||
} catch (ParserConfigurationException e) {
|
||||
continue;
|
||||
} catch (SAXException e) {
|
||||
continue;
|
||||
} catch (IOException e) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File outputDirectoryFile = new File(options.outputDirectory);
|
||||
if (!outputDirectoryFile.exists()) {
|
||||
if (!outputDirectoryFile.mkdirs()) {
|
||||
System.err.println("Can't create the output directory " + options.outputDirectory);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//sort the classes, so that if we're on a case-insensitive file system and need to handle classes with file
|
||||
//name collisions, then we'll use the same name for each class, if the dex file goes through multiple
|
||||
//baksmali/smali cycles for some reason. If a class with a colliding name is added or removed, the filenames
|
||||
//may still change of course
|
||||
List<? extends ClassDef> classDefs = Ordering.natural().sortedCopy(dexFile.getClasses());
|
||||
|
||||
if (!options.noAccessorComments) {
|
||||
options.syntheticAccessorResolver = new SyntheticAccessorResolver(classDefs);
|
||||
}
|
||||
|
||||
final ClassFileNameHandler fileNameHandler = new ClassFileNameHandler(outputDirectoryFile, ".smali");
|
||||
|
||||
ExecutorService executor = Executors.newFixedThreadPool(options.jobs);
|
||||
List<Future<Boolean>> tasks = Lists.newArrayList();
|
||||
|
||||
for (final ClassDef classDef: classDefs) {
|
||||
tasks.add(executor.submit(new Callable<Boolean>() {
|
||||
@Override public Boolean call() throws Exception {
|
||||
return disassembleClass(classDef, fileNameHandler, options);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
boolean errorOccurred = false;
|
||||
try {
|
||||
for (Future<Boolean> task: tasks) {
|
||||
while(true) {
|
||||
try {
|
||||
if (!task.get()) {
|
||||
errorOccurred = true;
|
||||
}
|
||||
} catch (InterruptedException ex) {
|
||||
continue;
|
||||
} catch (ExecutionException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
executor.shutdown();
|
||||
}
|
||||
return !errorOccurred;
|
||||
}
|
||||
|
||||
private static boolean disassembleClass(ClassDef classDef, ClassFileNameHandler fileNameHandler,
|
||||
baksmaliOptions options) {
|
||||
/**
|
||||
* The path for the disassembly file is based on the package name
|
||||
* The class descriptor will look something like:
|
||||
* Ljava/lang/Object;
|
||||
* Where the there is leading 'L' and a trailing ';', and the parts of the
|
||||
* package name are separated by '/'
|
||||
*/
|
||||
String classDescriptor = classDef.getType();
|
||||
|
||||
//validate that the descriptor is formatted like we expect
|
||||
if (classDescriptor.charAt(0) != 'L' ||
|
||||
classDescriptor.charAt(classDescriptor.length()-1) != ';') {
|
||||
System.err.println("Unrecognized class descriptor - " + classDescriptor + " - skipping class");
|
||||
return false;
|
||||
}
|
||||
|
||||
File smaliFile = fileNameHandler.getUniqueFilenameForClass(classDescriptor);
|
||||
|
||||
//create and initialize the top level string template
|
||||
ClassDefinition classDefinition = new ClassDefinition(options, classDef);
|
||||
|
||||
//write the disassembly
|
||||
Writer writer = null;
|
||||
try
|
||||
{
|
||||
File smaliParent = smaliFile.getParentFile();
|
||||
if (!smaliParent.exists()) {
|
||||
if (!smaliParent.mkdirs()) {
|
||||
// check again, it's likely it was created in a different thread
|
||||
if (!smaliParent.exists()) {
|
||||
System.err.println("Unable to create directory " + smaliParent.toString() + " - skipping class");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!smaliFile.exists()){
|
||||
if (!smaliFile.createNewFile()) {
|
||||
System.err.println("Unable to create file " + smaliFile.toString() + " - skipping class");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
BufferedWriter bufWriter = new BufferedWriter(new OutputStreamWriter(
|
||||
new FileOutputStream(smaliFile), "UTF8"));
|
||||
|
||||
writer = new IndentingWriter(bufWriter);
|
||||
classDefinition.writeTo((IndentingWriter)writer);
|
||||
} catch (Exception ex) {
|
||||
System.err.println("\n\nError occurred while disassembling class " + classDescriptor.replace('/', '.') + " - skipping class");
|
||||
ex.printStackTrace();
|
||||
// noinspection ResultOfMethodCallIgnored
|
||||
smaliFile.delete();
|
||||
return false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (writer != null) {
|
||||
try {
|
||||
writer.close();
|
||||
} catch (Throwable ex) {
|
||||
System.err.println("\n\nError occurred while closing file " + smaliFile.toString());
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,105 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import org.jf.dexlib2.analysis.ClassPath;
|
||||
import org.jf.dexlib2.analysis.InlineMethodResolver;
|
||||
import org.jf.dexlib2.util.SyntheticAccessorResolver;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class baksmaliOptions {
|
||||
// register info values
|
||||
public static final int ALL = 1;
|
||||
public static final int ALLPRE = 2;
|
||||
public static final int ALLPOST = 4;
|
||||
public static final int ARGS = 8;
|
||||
public static final int DEST = 16;
|
||||
public static final int MERGE = 32;
|
||||
public static final int FULLMERGE = 64;
|
||||
|
||||
public static final int DIFFPRE = 128;
|
||||
|
||||
public int apiLevel = 15;
|
||||
public String outputDirectory = "out";
|
||||
public String dexEntry = "classes.dex";
|
||||
public List<String> bootClassPathDirs = Lists.newArrayList();
|
||||
|
||||
public List<String> bootClassPathEntries = Lists.newArrayList();
|
||||
public List<String> extraClassPathEntries = Lists.newArrayList();
|
||||
|
||||
public Map<String,String> resourceIdFileEntries = new HashMap<String,String>();
|
||||
public Map<Integer,String> resourceIds = new HashMap<Integer,String>();
|
||||
|
||||
public boolean noParameterRegisters = false;
|
||||
public boolean useLocalsDirective = false;
|
||||
public boolean useSequentialLabels = false;
|
||||
public boolean outputDebugInfo = true;
|
||||
public boolean addCodeOffsets = false;
|
||||
public boolean noAccessorComments = false;
|
||||
public boolean allowOdex = false;
|
||||
public boolean deodex = false;
|
||||
public boolean experimental = false;
|
||||
public boolean ignoreErrors = false;
|
||||
public boolean checkPackagePrivateAccess = false;
|
||||
public boolean useImplicitReferences = false;
|
||||
public File customInlineDefinitions = null;
|
||||
public InlineMethodResolver inlineResolver = null;
|
||||
public int registerInfo = 0;
|
||||
public ClassPath classPath = null;
|
||||
public int jobs = -1;
|
||||
|
||||
public SyntheticAccessorResolver syntheticAccessorResolver = null;
|
||||
|
||||
public void setBootClassPath(String bootClassPath) {
|
||||
bootClassPathEntries = Lists.newArrayList(bootClassPath.split(":"));
|
||||
}
|
||||
|
||||
public void addExtraClassPath(String extraClassPath) {
|
||||
if (extraClassPath.startsWith(":")) {
|
||||
extraClassPath = extraClassPath.substring(1);
|
||||
}
|
||||
extraClassPathEntries.addAll(Arrays.asList(extraClassPath.split(":")));
|
||||
}
|
||||
|
||||
public void setResourceIdFiles(String resourceIdFiles) {
|
||||
for (String resourceIdFile: resourceIdFiles.split(":")) {
|
||||
String[] entry = resourceIdFile.split("=");
|
||||
resourceIdFileEntries.put(entry[1], entry[0]);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 Ben Gruver (JesusFreke)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali;
|
||||
|
||||
import org.jf.dexlib2.Opcodes;
|
||||
import org.jf.dexlib2.dexbacked.DexBackedDexFile;
|
||||
import org.jf.dexlib2.dexbacked.raw.RawDexFile;
|
||||
import org.jf.dexlib2.dexbacked.raw.util.DexAnnotator;
|
||||
import org.jf.util.ConsoleUtil;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
|
||||
public class dump {
|
||||
public static void dump(DexBackedDexFile dexFile, String dumpFileName, int apiLevel, boolean experimental) throws IOException {
|
||||
if (dumpFileName != null) {
|
||||
Writer writer = null;
|
||||
|
||||
try {
|
||||
writer = new BufferedWriter(new FileWriter(dumpFileName));
|
||||
|
||||
int consoleWidth = ConsoleUtil.getConsoleWidth();
|
||||
if (consoleWidth <= 0) {
|
||||
consoleWidth = 120;
|
||||
}
|
||||
|
||||
RawDexFile rawDexFile = new RawDexFile(new Opcodes(apiLevel, experimental), dexFile);
|
||||
DexAnnotator annotator = new DexAnnotator(rawDexFile, consoleWidth);
|
||||
annotator.writeAnnotations(writer);
|
||||
} catch (IOException ex) {
|
||||
System.err.println("There was an error while dumping the dex file to " + dumpFileName);
|
||||
ex.printStackTrace(System.err);
|
||||
} finally {
|
||||
if (writer != null) {
|
||||
try {
|
||||
writer.close();
|
||||
} catch (IOException ex) {
|
||||
System.err.println("There was an error while closing the dump file " + dumpFileName);
|
||||
ex.printStackTrace(System.err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,566 +0,0 @@
|
||||
/*
|
||||
* [The "BSD licence"]
|
||||
* Copyright (c) 2010 Ben Gruver (JesusFreke)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import org.apache.commons.cli.*;
|
||||
import org.jf.dexlib2.DexFileFactory;
|
||||
import org.jf.dexlib2.analysis.InlineMethodResolver;
|
||||
import org.jf.dexlib2.dexbacked.DexBackedDexFile;
|
||||
import org.jf.dexlib2.dexbacked.DexBackedOdexFile;
|
||||
import org.jf.util.ConsoleUtil;
|
||||
import org.jf.util.SmaliHelpFormatter;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Properties;
|
||||
|
||||
public class main {
|
||||
|
||||
public static final String VERSION;
|
||||
|
||||
private static final Options basicOptions;
|
||||
private static final Options debugOptions;
|
||||
private static final Options options;
|
||||
|
||||
static {
|
||||
options = new Options();
|
||||
basicOptions = new Options();
|
||||
debugOptions = new Options();
|
||||
buildOptions();
|
||||
|
||||
InputStream templateStream = baksmali.class.getClassLoader().getResourceAsStream("baksmali.properties");
|
||||
if (templateStream != null) {
|
||||
Properties properties = new Properties();
|
||||
String version = "(unknown)";
|
||||
try {
|
||||
properties.load(templateStream);
|
||||
version = properties.getProperty("application.version");
|
||||
} catch (IOException ex) {
|
||||
// ignore
|
||||
}
|
||||
VERSION = version;
|
||||
} else {
|
||||
VERSION = "[unknown version]";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This class is uninstantiable.
|
||||
*/
|
||||
private main() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Run!
|
||||
*/
|
||||
public static void main(String[] args) throws IOException {
|
||||
Locale locale = new Locale("en", "US");
|
||||
Locale.setDefault(locale);
|
||||
|
||||
CommandLineParser parser = new PosixParser();
|
||||
CommandLine commandLine;
|
||||
|
||||
try {
|
||||
commandLine = parser.parse(options, args);
|
||||
} catch (ParseException ex) {
|
||||
usage();
|
||||
return;
|
||||
}
|
||||
|
||||
baksmaliOptions options = new baksmaliOptions();
|
||||
|
||||
boolean disassemble = true;
|
||||
boolean doDump = false;
|
||||
String dumpFileName = null;
|
||||
boolean setBootClassPath = false;
|
||||
|
||||
String[] remainingArgs = commandLine.getArgs();
|
||||
Option[] clOptions = commandLine.getOptions();
|
||||
|
||||
for (int i=0; i<clOptions.length; i++) {
|
||||
Option option = clOptions[i];
|
||||
String opt = option.getOpt();
|
||||
|
||||
switch (opt.charAt(0)) {
|
||||
case 'v':
|
||||
version();
|
||||
return;
|
||||
case '?':
|
||||
while (++i < clOptions.length) {
|
||||
if (clOptions[i].getOpt().charAt(0) == '?') {
|
||||
usage(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
usage(false);
|
||||
return;
|
||||
case 'o':
|
||||
options.outputDirectory = commandLine.getOptionValue("o");
|
||||
break;
|
||||
case 'p':
|
||||
options.noParameterRegisters = true;
|
||||
break;
|
||||
case 'l':
|
||||
options.useLocalsDirective = true;
|
||||
break;
|
||||
case 's':
|
||||
options.useSequentialLabels = true;
|
||||
break;
|
||||
case 'b':
|
||||
options.outputDebugInfo = false;
|
||||
break;
|
||||
case 'd':
|
||||
options.bootClassPathDirs.add(option.getValue());
|
||||
break;
|
||||
case 'f':
|
||||
options.addCodeOffsets = true;
|
||||
break;
|
||||
case 'r':
|
||||
String[] values = commandLine.getOptionValues('r');
|
||||
int registerInfo = 0;
|
||||
|
||||
if (values == null || values.length == 0) {
|
||||
registerInfo = baksmaliOptions.ARGS | baksmaliOptions.DEST;
|
||||
} else {
|
||||
for (String value: values) {
|
||||
if (value.equalsIgnoreCase("ALL")) {
|
||||
registerInfo |= baksmaliOptions.ALL;
|
||||
} else if (value.equalsIgnoreCase("ALLPRE")) {
|
||||
registerInfo |= baksmaliOptions.ALLPRE;
|
||||
} else if (value.equalsIgnoreCase("ALLPOST")) {
|
||||
registerInfo |= baksmaliOptions.ALLPOST;
|
||||
} else if (value.equalsIgnoreCase("ARGS")) {
|
||||
registerInfo |= baksmaliOptions.ARGS;
|
||||
} else if (value.equalsIgnoreCase("DEST")) {
|
||||
registerInfo |= baksmaliOptions.DEST;
|
||||
} else if (value.equalsIgnoreCase("MERGE")) {
|
||||
registerInfo |= baksmaliOptions.MERGE;
|
||||
} else if (value.equalsIgnoreCase("FULLMERGE")) {
|
||||
registerInfo |= baksmaliOptions.FULLMERGE;
|
||||
} else {
|
||||
usage();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ((registerInfo & baksmaliOptions.FULLMERGE) != 0) {
|
||||
registerInfo &= ~baksmaliOptions.MERGE;
|
||||
}
|
||||
}
|
||||
options.registerInfo = registerInfo;
|
||||
break;
|
||||
case 'c':
|
||||
String bcp = commandLine.getOptionValue("c");
|
||||
if (bcp != null && bcp.charAt(0) == ':') {
|
||||
options.addExtraClassPath(bcp);
|
||||
} else {
|
||||
setBootClassPath = true;
|
||||
options.setBootClassPath(bcp);
|
||||
}
|
||||
break;
|
||||
case 'x':
|
||||
options.deodex = true;
|
||||
break;
|
||||
case 'X':
|
||||
options.experimental = true;
|
||||
break;
|
||||
case 'm':
|
||||
options.noAccessorComments = true;
|
||||
break;
|
||||
case 'a':
|
||||
options.apiLevel = Integer.parseInt(commandLine.getOptionValue("a"));
|
||||
break;
|
||||
case 'j':
|
||||
options.jobs = Integer.parseInt(commandLine.getOptionValue("j"));
|
||||
break;
|
||||
case 'i':
|
||||
String rif = commandLine.getOptionValue("i");
|
||||
options.setResourceIdFiles(rif);
|
||||
break;
|
||||
case 't':
|
||||
options.useImplicitReferences = true;
|
||||
break;
|
||||
case 'e':
|
||||
options.dexEntry = commandLine.getOptionValue("e");
|
||||
break;
|
||||
case 'k':
|
||||
options.checkPackagePrivateAccess = true;
|
||||
break;
|
||||
case 'N':
|
||||
disassemble = false;
|
||||
break;
|
||||
case 'D':
|
||||
doDump = true;
|
||||
dumpFileName = commandLine.getOptionValue("D");
|
||||
break;
|
||||
case 'I':
|
||||
options.ignoreErrors = true;
|
||||
break;
|
||||
case 'T':
|
||||
options.customInlineDefinitions = new File(commandLine.getOptionValue("T"));
|
||||
break;
|
||||
default:
|
||||
assert false;
|
||||
}
|
||||
}
|
||||
|
||||
if (remainingArgs.length != 1) {
|
||||
usage();
|
||||
return;
|
||||
}
|
||||
|
||||
if (options.jobs <= 0) {
|
||||
options.jobs = Runtime.getRuntime().availableProcessors();
|
||||
if (options.jobs > 6) {
|
||||
options.jobs = 6;
|
||||
}
|
||||
}
|
||||
|
||||
String inputDexFileName = remainingArgs[0];
|
||||
|
||||
File dexFileFile = new File(inputDexFileName);
|
||||
if (!dexFileFile.exists()) {
|
||||
System.err.println("Can't find the file " + inputDexFileName);
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
//Read in and parse the dex file
|
||||
DexBackedDexFile dexFile = DexFileFactory.loadDexFile(dexFileFile, options.dexEntry,
|
||||
options.apiLevel, options.experimental);
|
||||
|
||||
if (dexFile.isOdexFile()) {
|
||||
if (!options.deodex) {
|
||||
System.err.println("Warning: You are disassembling an odex file without deodexing it. You");
|
||||
System.err.println("won't be able to re-assemble the results unless you deodex it with the -x");
|
||||
System.err.println("option");
|
||||
options.allowOdex = true;
|
||||
}
|
||||
} else {
|
||||
options.deodex = false;
|
||||
}
|
||||
|
||||
if (!setBootClassPath && (options.deodex || options.registerInfo != 0)) {
|
||||
if (dexFile instanceof DexBackedOdexFile) {
|
||||
options.bootClassPathEntries = ((DexBackedOdexFile)dexFile).getDependencies();
|
||||
} else {
|
||||
options.bootClassPathEntries = getDefaultBootClassPathForApi(options.apiLevel,
|
||||
options.experimental);
|
||||
}
|
||||
}
|
||||
|
||||
if (options.customInlineDefinitions == null && dexFile instanceof DexBackedOdexFile) {
|
||||
options.inlineResolver =
|
||||
InlineMethodResolver.createInlineMethodResolver(
|
||||
((DexBackedOdexFile)dexFile).getOdexVersion());
|
||||
}
|
||||
|
||||
boolean errorOccurred = false;
|
||||
if (disassemble) {
|
||||
errorOccurred = !baksmali.disassembleDexFile(dexFile, options);
|
||||
}
|
||||
|
||||
if (doDump) {
|
||||
if (dumpFileName == null) {
|
||||
dumpFileName = commandLine.getOptionValue(inputDexFileName + ".dump");
|
||||
}
|
||||
dump.dump(dexFile, dumpFileName, options.apiLevel, options.experimental);
|
||||
}
|
||||
|
||||
if (errorOccurred) {
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the usage message.
|
||||
*/
|
||||
private static void usage(boolean printDebugOptions) {
|
||||
SmaliHelpFormatter formatter = new SmaliHelpFormatter();
|
||||
int consoleWidth = ConsoleUtil.getConsoleWidth();
|
||||
if (consoleWidth <= 0) {
|
||||
consoleWidth = 80;
|
||||
}
|
||||
|
||||
formatter.setWidth(consoleWidth);
|
||||
|
||||
formatter.printHelp("java -jar baksmali.jar [options] <dex-file>",
|
||||
"disassembles and/or dumps a dex file", basicOptions, printDebugOptions?debugOptions:null);
|
||||
}
|
||||
|
||||
private static void usage() {
|
||||
usage(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the version message.
|
||||
*/
|
||||
protected static void version() {
|
||||
System.out.println("baksmali " + VERSION + " (http://smali.googlecode.com)");
|
||||
System.out.println("Copyright (C) 2010 Ben Gruver (JesusFreke@JesusFreke.com)");
|
||||
System.out.println("BSD license (http://www.opensource.org/licenses/bsd-license.php)");
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
@SuppressWarnings("AccessStaticViaInstance")
|
||||
private static void buildOptions() {
|
||||
Option versionOption = OptionBuilder.withLongOpt("version")
|
||||
.withDescription("prints the version then exits")
|
||||
.create("v");
|
||||
|
||||
Option helpOption = OptionBuilder.withLongOpt("help")
|
||||
.withDescription("prints the help message then exits. Specify twice for debug options")
|
||||
.create("?");
|
||||
|
||||
Option outputDirOption = OptionBuilder.withLongOpt("output")
|
||||
.withDescription("the directory where the disassembled files will be placed. The default is out")
|
||||
.hasArg()
|
||||
.withArgName("DIR")
|
||||
.create("o");
|
||||
|
||||
Option noParameterRegistersOption = OptionBuilder.withLongOpt("no-parameter-registers")
|
||||
.withDescription("use the v<n> syntax instead of the p<n> syntax for registers mapped to method " +
|
||||
"parameters")
|
||||
.create("p");
|
||||
|
||||
Option deodexerantOption = OptionBuilder.withLongOpt("deodex")
|
||||
.withDescription("deodex the given odex file. This option is ignored if the input file is not an " +
|
||||
"odex file")
|
||||
.create("x");
|
||||
|
||||
Option experimentalOption = OptionBuilder.withLongOpt("experimental")
|
||||
.withDescription("enable experimental opcodes to be disassembled, even if they aren't necessarily supported in the Android runtime yet")
|
||||
.create("X");
|
||||
|
||||
Option useLocalsOption = OptionBuilder.withLongOpt("use-locals")
|
||||
.withDescription("output the .locals directive with the number of non-parameter registers, rather" +
|
||||
" than the .register directive with the total number of register")
|
||||
.create("l");
|
||||
|
||||
Option sequentialLabelsOption = OptionBuilder.withLongOpt("sequential-labels")
|
||||
.withDescription("create label names using a sequential numbering scheme per label type, rather than " +
|
||||
"using the bytecode address")
|
||||
.create("s");
|
||||
|
||||
Option noDebugInfoOption = OptionBuilder.withLongOpt("no-debug-info")
|
||||
.withDescription("don't write out debug info (.local, .param, .line, etc.)")
|
||||
.create("b");
|
||||
|
||||
Option registerInfoOption = OptionBuilder.withLongOpt("register-info")
|
||||
.hasOptionalArgs()
|
||||
.withArgName("REGISTER_INFO_TYPES")
|
||||
.withValueSeparator(',')
|
||||
.withDescription("print the specificed type(s) of register information for each instruction. " +
|
||||
"\"ARGS,DEST\" is the default if no types are specified.\nValid values are:\nALL: all " +
|
||||
"pre- and post-instruction registers.\nALLPRE: all pre-instruction registers\nALLPOST: all " +
|
||||
"post-instruction registers\nARGS: any pre-instruction registers used as arguments to the " +
|
||||
"instruction\nDEST: the post-instruction destination register, if any\nMERGE: Any " +
|
||||
"pre-instruction register has been merged from more than 1 different post-instruction " +
|
||||
"register from its predecessors\nFULLMERGE: For each register that would be printed by " +
|
||||
"MERGE, also show the incoming register types that were merged")
|
||||
.create("r");
|
||||
|
||||
Option classPathOption = OptionBuilder.withLongOpt("bootclasspath")
|
||||
.withDescription("the bootclasspath jars to use, for analysis. Defaults to " +
|
||||
"core.jar:ext.jar:framework.jar:android.policy.jar:services.jar. If the value begins with a " +
|
||||
":, it will be appended to the default bootclasspath instead of replacing it")
|
||||
.hasOptionalArg()
|
||||
.withArgName("BOOTCLASSPATH")
|
||||
.create("c");
|
||||
|
||||
Option classPathDirOption = OptionBuilder.withLongOpt("bootclasspath-dir")
|
||||
.withDescription("the base folder to look for the bootclasspath files in. Defaults to the current " +
|
||||
"directory")
|
||||
.hasArg()
|
||||
.withArgName("DIR")
|
||||
.create("d");
|
||||
|
||||
Option codeOffsetOption = OptionBuilder.withLongOpt("code-offsets")
|
||||
.withDescription("add comments to the disassembly containing the code offset for each address")
|
||||
.create("f");
|
||||
|
||||
Option noAccessorCommentsOption = OptionBuilder.withLongOpt("no-accessor-comments")
|
||||
.withDescription("don't output helper comments for synthetic accessors")
|
||||
.create("m");
|
||||
|
||||
Option apiLevelOption = OptionBuilder.withLongOpt("api-level")
|
||||
.withDescription("The numeric api-level of the file being disassembled. If not " +
|
||||
"specified, it defaults to 15 (ICS).")
|
||||
.hasArg()
|
||||
.withArgName("API_LEVEL")
|
||||
.create("a");
|
||||
|
||||
Option jobsOption = OptionBuilder.withLongOpt("jobs")
|
||||
.withDescription("The number of threads to use. Defaults to the number of cores available, up to a " +
|
||||
"maximum of 6")
|
||||
.hasArg()
|
||||
.withArgName("NUM_THREADS")
|
||||
.create("j");
|
||||
|
||||
Option resourceIdFilesOption = OptionBuilder.withLongOpt("resource-id-files")
|
||||
.withDescription("the resource ID files to use, for analysis. A colon-separated list of prefix=file " +
|
||||
"pairs. For example R=res/values/public.xml:" +
|
||||
"android.R=$ANDROID_HOME/platforms/android-19/data/res/values/public.xml")
|
||||
.hasArg()
|
||||
.withArgName("FILES")
|
||||
.create("i");
|
||||
|
||||
Option noImplicitReferencesOption = OptionBuilder.withLongOpt("implicit-references")
|
||||
.withDescription("Use implicit (type-less) method and field references")
|
||||
.create("t");
|
||||
|
||||
Option checkPackagePrivateAccessOption = OptionBuilder.withLongOpt("check-package-private-access")
|
||||
.withDescription("When deodexing, use the package-private access check when calculating vtable " +
|
||||
"indexes. It should only be needed for 4.2.0 odexes. The functionality was reverted for " +
|
||||
"4.2.1.")
|
||||
.create("k");
|
||||
|
||||
Option dumpOption = OptionBuilder.withLongOpt("dump-to")
|
||||
.withDescription("dumps the given dex file into a single annotated dump file named FILE" +
|
||||
" (<dexfile>.dump by default), along with the normal disassembly")
|
||||
.hasOptionalArg()
|
||||
.withArgName("FILE")
|
||||
.create("D");
|
||||
|
||||
Option ignoreErrorsOption = OptionBuilder.withLongOpt("ignore-errors")
|
||||
.withDescription("ignores any non-fatal errors that occur while disassembling/deodexing," +
|
||||
" ignoring the class if needed, and continuing with the next class. The default" +
|
||||
" behavior is to stop disassembling and exit once an error is encountered")
|
||||
.create("I");
|
||||
|
||||
Option noDisassemblyOption = OptionBuilder.withLongOpt("no-disassembly")
|
||||
.withDescription("suppresses the output of the disassembly")
|
||||
.create("N");
|
||||
|
||||
Option inlineTableOption = OptionBuilder.withLongOpt("inline-table")
|
||||
.withDescription("specify a file containing a custom inline method table to use for deodexing")
|
||||
.hasArg()
|
||||
.withArgName("FILE")
|
||||
.create("T");
|
||||
|
||||
Option dexEntryOption = OptionBuilder.withLongOpt("dex-file")
|
||||
.withDescription("looks for dex file named DEX_FILE, defaults to classes.dex")
|
||||
.withArgName("DEX_FILE")
|
||||
.hasArg()
|
||||
.create("e");
|
||||
|
||||
basicOptions.addOption(versionOption);
|
||||
basicOptions.addOption(helpOption);
|
||||
basicOptions.addOption(outputDirOption);
|
||||
basicOptions.addOption(noParameterRegistersOption);
|
||||
basicOptions.addOption(deodexerantOption);
|
||||
basicOptions.addOption(experimentalOption);
|
||||
basicOptions.addOption(useLocalsOption);
|
||||
basicOptions.addOption(sequentialLabelsOption);
|
||||
basicOptions.addOption(noDebugInfoOption);
|
||||
basicOptions.addOption(registerInfoOption);
|
||||
basicOptions.addOption(classPathOption);
|
||||
basicOptions.addOption(classPathDirOption);
|
||||
basicOptions.addOption(codeOffsetOption);
|
||||
basicOptions.addOption(noAccessorCommentsOption);
|
||||
basicOptions.addOption(apiLevelOption);
|
||||
basicOptions.addOption(jobsOption);
|
||||
basicOptions.addOption(resourceIdFilesOption);
|
||||
basicOptions.addOption(noImplicitReferencesOption);
|
||||
basicOptions.addOption(dexEntryOption);
|
||||
basicOptions.addOption(checkPackagePrivateAccessOption);
|
||||
|
||||
debugOptions.addOption(dumpOption);
|
||||
debugOptions.addOption(ignoreErrorsOption);
|
||||
debugOptions.addOption(noDisassemblyOption);
|
||||
debugOptions.addOption(inlineTableOption);
|
||||
|
||||
for (Object option: basicOptions.getOptions()) {
|
||||
options.addOption((Option)option);
|
||||
}
|
||||
for (Object option: debugOptions.getOptions()) {
|
||||
options.addOption((Option)option);
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private static List<String> getDefaultBootClassPathForApi(int apiLevel, boolean experimental) {
|
||||
if (apiLevel < 9) {
|
||||
return Lists.newArrayList(
|
||||
"/system/framework/core.jar",
|
||||
"/system/framework/ext.jar",
|
||||
"/system/framework/framework.jar",
|
||||
"/system/framework/android.policy.jar",
|
||||
"/system/framework/services.jar");
|
||||
} else if (apiLevel < 12) {
|
||||
return Lists.newArrayList(
|
||||
"/system/framework/core.jar",
|
||||
"/system/framework/bouncycastle.jar",
|
||||
"/system/framework/ext.jar",
|
||||
"/system/framework/framework.jar",
|
||||
"/system/framework/android.policy.jar",
|
||||
"/system/framework/services.jar",
|
||||
"/system/framework/core-junit.jar");
|
||||
} else if (apiLevel < 14) {
|
||||
return Lists.newArrayList(
|
||||
"/system/framework/core.jar",
|
||||
"/system/framework/apache-xml.jar",
|
||||
"/system/framework/bouncycastle.jar",
|
||||
"/system/framework/ext.jar",
|
||||
"/system/framework/framework.jar",
|
||||
"/system/framework/android.policy.jar",
|
||||
"/system/framework/services.jar",
|
||||
"/system/framework/core-junit.jar");
|
||||
} else if (apiLevel < 16) {
|
||||
return Lists.newArrayList(
|
||||
"/system/framework/core.jar",
|
||||
"/system/framework/core-junit.jar",
|
||||
"/system/framework/bouncycastle.jar",
|
||||
"/system/framework/ext.jar",
|
||||
"/system/framework/framework.jar",
|
||||
"/system/framework/android.policy.jar",
|
||||
"/system/framework/services.jar",
|
||||
"/system/framework/apache-xml.jar",
|
||||
"/system/framework/filterfw.jar");
|
||||
|
||||
} else {
|
||||
// this is correct as of api 17/4.2.2
|
||||
return Lists.newArrayList(
|
||||
"/system/framework/core.jar",
|
||||
"/system/framework/core-junit.jar",
|
||||
"/system/framework/bouncycastle.jar",
|
||||
"/system/framework/ext.jar",
|
||||
"/system/framework/framework.jar",
|
||||
"/system/framework/telephony-common.jar",
|
||||
"/system/framework/mms-common.jar",
|
||||
"/system/framework/android.policy.jar",
|
||||
"/system/framework/services.jar",
|
||||
"/system/framework/apache-xml.jar");
|
||||
}
|
||||
}
|
||||
}
|
@ -1 +0,0 @@
|
||||
application.version=${version}
|
@ -1,125 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.io.Resources;
|
||||
import junit.framework.Assert;
|
||||
import org.jf.baksmali.Adaptors.ClassDefinition;
|
||||
import org.jf.dexlib2.DexFileFactory;
|
||||
import org.jf.dexlib2.analysis.ClassPath;
|
||||
import org.jf.dexlib2.iface.ClassDef;
|
||||
import org.jf.dexlib2.iface.DexFile;
|
||||
import org.jf.util.IndentingWriter;
|
||||
import org.jf.util.TextUtils;
|
||||
import org.junit.Test;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
|
||||
public class AnalysisTest {
|
||||
|
||||
@Test
|
||||
public void ConstructorTest() throws IOException, URISyntaxException {
|
||||
runTest("ConstructorTest", true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void RegisterEqualityOnMergeTest() throws IOException, URISyntaxException {
|
||||
runTest("RegisterEqualityOnMergeTest", true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void UninitRefIdentityTest() throws IOException, URISyntaxException {
|
||||
runTest("UninitRefIdentityTest", true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void MultipleStartInstructionsTest() throws IOException, URISyntaxException {
|
||||
runTest("MultipleStartInstructionsTest", true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void DuplicateTest() throws IOException, URISyntaxException {
|
||||
runTest("DuplicateTest", false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void LocalTest() throws IOException, URISyntaxException {
|
||||
runTest("LocalTest", false);
|
||||
}
|
||||
|
||||
public void runTest(String test, boolean registerInfo) throws IOException, URISyntaxException {
|
||||
String dexFilePath = String.format("%s%sclasses.dex", test, File.separatorChar);
|
||||
|
||||
DexFile dexFile = DexFileFactory.loadDexFile(findResource(dexFilePath), 15, false);
|
||||
|
||||
baksmaliOptions options = new baksmaliOptions();
|
||||
if (registerInfo) {
|
||||
options.registerInfo = baksmaliOptions.ALL | baksmaliOptions.FULLMERGE;
|
||||
options.classPath = new ClassPath();
|
||||
}
|
||||
options.useImplicitReferences = false;
|
||||
|
||||
for (ClassDef classDef: dexFile.getClasses()) {
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
IndentingWriter writer = new IndentingWriter(stringWriter);
|
||||
ClassDefinition classDefinition = new ClassDefinition(options, classDef);
|
||||
classDefinition.writeTo(writer);
|
||||
writer.close();
|
||||
|
||||
String className = classDef.getType();
|
||||
String smaliPath = String.format("%s%s%s.smali", test, File.separatorChar,
|
||||
className.substring(1, className.length() - 1));
|
||||
String smaliContents = readResource(smaliPath);
|
||||
|
||||
Assert.assertEquals(TextUtils.normalizeNewlines(smaliContents),
|
||||
TextUtils.normalizeNewlines(stringWriter.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private File findResource(String resource) throws URISyntaxException {
|
||||
URL resUrl = Resources.getResource(resource);
|
||||
return new File(resUrl.toURI());
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private String readResource(String resource) throws URISyntaxException, IOException {
|
||||
URL url = Resources.getResource(resource);
|
||||
return Resources.toString(url, Charsets.UTF_8);
|
||||
}
|
||||
}
|
@ -1,119 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali;
|
||||
|
||||
import com.google.common.io.ByteStreams;
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.antlr.runtime.RecognitionException;
|
||||
import org.jf.baksmali.Adaptors.ClassDefinition;
|
||||
import org.jf.dexlib2.iface.ClassDef;
|
||||
import org.jf.smali.SmaliTestUtils;
|
||||
import org.jf.util.IndentingWriter;
|
||||
import org.jf.util.TextUtils;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.StringWriter;
|
||||
|
||||
public class BaksmaliTestUtils {
|
||||
public static void assertSmaliCompiledEquals(String source, String expected,
|
||||
baksmaliOptions options, boolean stripComments) throws IOException,
|
||||
RecognitionException {
|
||||
ClassDef classDef = SmaliTestUtils.compileSmali(source, options.apiLevel,
|
||||
options.experimental);
|
||||
|
||||
// Remove unnecessary whitespace and optionally strip all comments from smali file
|
||||
String normalizedActual = getNormalizedSmali(classDef, options, stripComments);
|
||||
String normalizedExpected = normalizeSmali(expected, stripComments);
|
||||
|
||||
// Assert that normalized strings are now equal
|
||||
Assert.assertEquals(normalizedExpected, normalizedActual);
|
||||
}
|
||||
|
||||
public static void assertSmaliCompiledEquals(String source, String expected,
|
||||
baksmaliOptions options) throws IOException, RecognitionException {
|
||||
assertSmaliCompiledEquals(source, expected, options, false);
|
||||
}
|
||||
|
||||
public static void assertSmaliCompiledEquals(String source, String expected)
|
||||
throws IOException, RecognitionException {
|
||||
baksmaliOptions options = new baksmaliOptions();
|
||||
assertSmaliCompiledEquals(source, expected, options);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static String normalizeSmali(@Nonnull String smaliText, boolean stripComments) {
|
||||
if (stripComments) {
|
||||
smaliText = TextUtils.stripComments(smaliText);
|
||||
}
|
||||
return TextUtils.normalizeWhitespace(smaliText);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static String getNormalizedSmali(@Nonnull ClassDef classDef, @Nonnull baksmaliOptions options,
|
||||
boolean stripComments)
|
||||
throws IOException {
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
IndentingWriter writer = new IndentingWriter(stringWriter);
|
||||
ClassDefinition classDefinition = new ClassDefinition(options, classDef);
|
||||
classDefinition.writeTo(writer);
|
||||
writer.close();
|
||||
return normalizeSmali(stringWriter.toString(), stripComments);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static byte[] readResourceBytesFully(@Nonnull String fileName) throws IOException {
|
||||
InputStream smaliStream = RoundtripTest.class.getClassLoader().
|
||||
getResourceAsStream(fileName);
|
||||
if (smaliStream == null) {
|
||||
org.junit.Assert.fail("Could not load " + fileName);
|
||||
}
|
||||
|
||||
return ByteStreams.toByteArray(smaliStream);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static String readResourceFully(@Nonnull String fileName) throws IOException {
|
||||
return readResourceFully(fileName, "UTF-8");
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static String readResourceFully(@Nonnull String fileName, @Nonnull String encoding)
|
||||
throws IOException {
|
||||
return new String(readResourceBytesFully(fileName), encoding);
|
||||
}
|
||||
|
||||
// Static helpers class; do not instantiate.
|
||||
private BaksmaliTestUtils() { throw new AssertionError(); }
|
||||
}
|
@ -1,104 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
import org.jf.dexlib2.Opcodes;
|
||||
import org.jf.dexlib2.dexbacked.DexBackedDexFile;
|
||||
import org.jf.dexlib2.iface.ClassDef;
|
||||
import org.junit.Assert;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* A base test class for performing a disassembly on a dex file and verifying the results
|
||||
*
|
||||
* The test accepts a single-class dex file as input, disassembles it, and verifies that
|
||||
* the result equals a known-good output smali file.
|
||||
*
|
||||
* By default, the input and output files should be resources at [testDir]/[testName]Input.dex
|
||||
* and [testDir]/[testName]Output.smali respectively
|
||||
*/
|
||||
public class DisassemblyTest {
|
||||
protected final String testDir;
|
||||
|
||||
protected DisassemblyTest(@Nonnull String testDir) {
|
||||
this.testDir = testDir;
|
||||
}
|
||||
|
||||
protected DisassemblyTest() {
|
||||
this.testDir = this.getClass().getSimpleName();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
protected String getInputFilename(@Nonnull String testName) {
|
||||
return String.format("%s%s%sInput.dex", testDir, File.separatorChar, testName);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
protected String getOutputFilename(@Nonnull String testName) {
|
||||
return String.format("%s%s%sOutput.smali", testDir, File.separatorChar, testName);
|
||||
}
|
||||
|
||||
protected void runTest(@Nonnull String testName) {
|
||||
runTest(testName, new baksmaliOptions());
|
||||
}
|
||||
|
||||
protected void runTest(@Nonnull String testName, @Nonnull baksmaliOptions options) {
|
||||
try {
|
||||
// Load file from resources as a stream
|
||||
String inputFilename = getInputFilename(testName);
|
||||
byte[] inputBytes = BaksmaliTestUtils.readResourceBytesFully(getInputFilename(testName));
|
||||
|
||||
DexBackedDexFile inputDex = new DexBackedDexFile(new Opcodes(options.apiLevel, false), inputBytes);
|
||||
Assert.assertEquals(1, inputDex.getClassCount());
|
||||
ClassDef inputClass = Iterables.getFirst(inputDex.getClasses(), null);
|
||||
Assert.assertNotNull(inputClass);
|
||||
String input = BaksmaliTestUtils.getNormalizedSmali(inputClass, options, true);
|
||||
|
||||
String output;
|
||||
if (getOutputFilename(testName).equals(inputFilename)) {
|
||||
output = input;
|
||||
} else {
|
||||
output = BaksmaliTestUtils.readResourceFully(getOutputFilename(testName));
|
||||
}
|
||||
output = BaksmaliTestUtils.normalizeSmali(output, true);
|
||||
|
||||
// Run smali, baksmali, and then compare strings are equal (minus comments/whitespace)
|
||||
Assert.assertEquals(output, input);
|
||||
} catch (IOException ex) {
|
||||
Assert.fail();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* A base test class for performing a roundtrip assembly/disassembly where the input and output
|
||||
* should be identical.
|
||||
*
|
||||
* By default, the input/output file should be a resource at [testDir]/[testName].smali
|
||||
*/
|
||||
public abstract class IdenticalRoundtripTest extends RoundtripTest {
|
||||
|
||||
public IdenticalRoundtripTest(@Nonnull String testDir) {
|
||||
super(testDir);
|
||||
}
|
||||
|
||||
public IdenticalRoundtripTest() {
|
||||
}
|
||||
|
||||
@Nonnull @Override protected String getInputFilename(@Nonnull String testName) {
|
||||
return String.format("%s%s%s.smali", testDir, File.separatorChar, testName);
|
||||
}
|
||||
|
||||
@Nonnull @Override protected String getOutputFilename(@Nonnull String testName) {
|
||||
return getInputFilename(testName);
|
||||
}
|
||||
}
|
@ -1,260 +0,0 @@
|
||||
/*
|
||||
* Copyright 2014, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali;
|
||||
|
||||
import org.antlr.runtime.RecognitionException;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class ImplicitReferenceTest {
|
||||
@Test
|
||||
public void testImplicitMethodReferences() throws IOException, RecognitionException {
|
||||
String source = "" +
|
||||
".class public LHelloWorld;\n" +
|
||||
".super Ljava/lang/Object;\n" +
|
||||
".method public static main([Ljava/lang/String;)V\n" +
|
||||
" .registers 1\n" +
|
||||
" invoke-static {p0}, LHelloWorld;->toString()V\n" +
|
||||
" invoke-static {p0}, LHelloWorld;->V()V\n" +
|
||||
" invoke-static {p0}, LHelloWorld;->I()V\n" +
|
||||
" return-void\n" +
|
||||
".end method";
|
||||
|
||||
String expected = "" +
|
||||
".class public LHelloWorld;\n" +
|
||||
".super Ljava/lang/Object;\n" +
|
||||
"# direct methods\n" +
|
||||
".method public static main([Ljava/lang/String;)V\n" +
|
||||
".registers 1\n" +
|
||||
"invoke-static {p0}, toString()V\n" +
|
||||
"invoke-static {p0}, V()V\n" +
|
||||
"invoke-static {p0}, I()V\n" +
|
||||
"return-void\n" +
|
||||
".end method\n";
|
||||
|
||||
baksmaliOptions options = new baksmaliOptions();
|
||||
options.useImplicitReferences = true;
|
||||
|
||||
BaksmaliTestUtils.assertSmaliCompiledEquals(source, expected, options);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExplicitMethodReferences() throws IOException, RecognitionException {
|
||||
String source = "" +
|
||||
".class public LHelloWorld;\n" +
|
||||
".super Ljava/lang/Object;\n" +
|
||||
".method public static main([Ljava/lang/String;)V\n" +
|
||||
" .registers 1\n" +
|
||||
" invoke-static {p0}, LHelloWorld;->toString()V\n" +
|
||||
" invoke-static {p0}, LHelloWorld;->V()V\n" +
|
||||
" invoke-static {p0}, LHelloWorld;->I()V\n" +
|
||||
" return-void\n" +
|
||||
".end method";
|
||||
|
||||
String expected = "" +
|
||||
".class public LHelloWorld;\n" +
|
||||
".super Ljava/lang/Object;\n" +
|
||||
"# direct methods\n" +
|
||||
".method public static main([Ljava/lang/String;)V\n" +
|
||||
" .registers 1\n" +
|
||||
" invoke-static {p0}, LHelloWorld;->toString()V\n" +
|
||||
" invoke-static {p0}, LHelloWorld;->V()V\n" +
|
||||
" invoke-static {p0}, LHelloWorld;->I()V\n" +
|
||||
" return-void\n" +
|
||||
".end method\n";
|
||||
|
||||
baksmaliOptions options = new baksmaliOptions();
|
||||
options.useImplicitReferences = false;
|
||||
|
||||
BaksmaliTestUtils.assertSmaliCompiledEquals(source, expected, options);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testImplicitMethodLiterals() throws IOException, RecognitionException {
|
||||
String source = "" +
|
||||
".class public LHelloWorld;\n" +
|
||||
".super Ljava/lang/Object;\n" +
|
||||
".field public static field1:Ljava/lang/reflect/Method; = LHelloWorld;->toString()V\n" +
|
||||
".field public static field2:Ljava/lang/reflect/Method; = LHelloWorld;->V()V\n" +
|
||||
".field public static field3:Ljava/lang/reflect/Method; = LHelloWorld;->I()V\n" +
|
||||
".field public static field4:Ljava/lang/Class; = I";
|
||||
|
||||
String expected = "" +
|
||||
".class public LHelloWorld;\n" +
|
||||
".super Ljava/lang/Object;\n" +
|
||||
"# static fields\n" +
|
||||
".field public static field1:Ljava/lang/reflect/Method; = toString()V\n" +
|
||||
".field public static field2:Ljava/lang/reflect/Method; = V()V\n" +
|
||||
".field public static field3:Ljava/lang/reflect/Method; = I()V\n" +
|
||||
".field public static field4:Ljava/lang/Class; = I\n";
|
||||
|
||||
baksmaliOptions options = new baksmaliOptions();
|
||||
options.useImplicitReferences = true;
|
||||
|
||||
BaksmaliTestUtils.assertSmaliCompiledEquals(source, expected, options);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExplicitMethodLiterals() throws IOException, RecognitionException {
|
||||
String source = "" +
|
||||
".class public LHelloWorld;\n" +
|
||||
".super Ljava/lang/Object;\n" +
|
||||
".field public static field1:Ljava/lang/reflect/Method; = LHelloWorld;->toString()V\n" +
|
||||
".field public static field2:Ljava/lang/reflect/Method; = LHelloWorld;->V()V\n" +
|
||||
".field public static field3:Ljava/lang/reflect/Method; = LHelloWorld;->I()V\n" +
|
||||
".field public static field4:Ljava/lang/Class; = I";
|
||||
|
||||
String expected = "" +
|
||||
".class public LHelloWorld;\n" +
|
||||
".super Ljava/lang/Object;\n" +
|
||||
"# static fields\n" +
|
||||
".field public static field1:Ljava/lang/reflect/Method; = LHelloWorld;->toString()V\n" +
|
||||
".field public static field2:Ljava/lang/reflect/Method; = LHelloWorld;->V()V\n" +
|
||||
".field public static field3:Ljava/lang/reflect/Method; = LHelloWorld;->I()V\n" +
|
||||
".field public static field4:Ljava/lang/Class; = I\n";
|
||||
|
||||
baksmaliOptions options = new baksmaliOptions();
|
||||
options.useImplicitReferences = false;
|
||||
|
||||
BaksmaliTestUtils.assertSmaliCompiledEquals(source, expected, options);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testImplicitFieldReferences() throws IOException, RecognitionException {
|
||||
String source = "" +
|
||||
".class public LHelloWorld;\n" +
|
||||
".super Ljava/lang/Object;\n" +
|
||||
".method public static main([Ljava/lang/String;)V\n" +
|
||||
" .registers 1\n" +
|
||||
" sget v0, LHelloWorld;->someField:I\n" +
|
||||
" sget v0, LHelloWorld;->I:I\n" +
|
||||
" sget v0, LHelloWorld;->V:I\n" +
|
||||
" return-void\n" +
|
||||
".end method";
|
||||
|
||||
String expected = "" +
|
||||
".class public LHelloWorld;\n" +
|
||||
".super Ljava/lang/Object;\n" +
|
||||
"# direct methods\n" +
|
||||
".method public static main([Ljava/lang/String;)V\n" +
|
||||
" .registers 1\n" +
|
||||
" sget p0, someField:I\n" +
|
||||
" sget p0, I:I\n" +
|
||||
" sget p0, V:I\n" +
|
||||
" return-void\n" +
|
||||
".end method\n";
|
||||
|
||||
baksmaliOptions options = new baksmaliOptions();
|
||||
options.useImplicitReferences = true;
|
||||
|
||||
BaksmaliTestUtils.assertSmaliCompiledEquals(source, expected, options);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExplicitFieldReferences() throws IOException, RecognitionException {
|
||||
String source = "" +
|
||||
".class public LHelloWorld;\n" +
|
||||
".super Ljava/lang/Object;\n" +
|
||||
".method public static main([Ljava/lang/String;)V\n" +
|
||||
" .registers 1\n" +
|
||||
" sget v0, LHelloWorld;->someField:I\n" +
|
||||
" sget v0, LHelloWorld;->I:I\n" +
|
||||
" sget v0, LHelloWorld;->V:I\n" +
|
||||
" return-void\n" +
|
||||
".end method";
|
||||
|
||||
String expected = "" +
|
||||
".class public LHelloWorld;\n" +
|
||||
".super Ljava/lang/Object;\n" +
|
||||
"# direct methods\n" +
|
||||
".method public static main([Ljava/lang/String;)V\n" +
|
||||
" .registers 1\n" +
|
||||
" sget p0, LHelloWorld;->someField:I\n" +
|
||||
" sget p0, LHelloWorld;->I:I\n" +
|
||||
" sget p0, LHelloWorld;->V:I\n" +
|
||||
" return-void\n" +
|
||||
".end method\n";
|
||||
|
||||
baksmaliOptions options = new baksmaliOptions();
|
||||
options.useImplicitReferences = false;
|
||||
|
||||
BaksmaliTestUtils.assertSmaliCompiledEquals(source, expected, options);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testImplicitFieldLiterals() throws IOException, RecognitionException {
|
||||
String source = "" +
|
||||
".class public LHelloWorld;\n" +
|
||||
".super Ljava/lang/Object;\n" +
|
||||
".field public static field1:Ljava/lang/reflect/Field; = LHelloWorld;->someField:I\n" +
|
||||
".field public static field2:Ljava/lang/reflect/Field; = LHelloWorld;->V:I\n" +
|
||||
".field public static field3:Ljava/lang/reflect/Field; = LHelloWorld;->I:I";
|
||||
|
||||
String expected = "" +
|
||||
".class public LHelloWorld;\n" +
|
||||
".super Ljava/lang/Object;\n" +
|
||||
"# static fields\n" +
|
||||
".field public static field1:Ljava/lang/reflect/Field; = someField:I\n" +
|
||||
".field public static field2:Ljava/lang/reflect/Field; = V:I\n" +
|
||||
".field public static field3:Ljava/lang/reflect/Field; = I:I\n";
|
||||
|
||||
baksmaliOptions options = new baksmaliOptions();
|
||||
options.useImplicitReferences = true;
|
||||
|
||||
BaksmaliTestUtils.assertSmaliCompiledEquals(source, expected, options);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExplicitFieldLiterals() throws IOException, RecognitionException {
|
||||
String source = "" +
|
||||
".class public LHelloWorld;\n" +
|
||||
".super Ljava/lang/Object;\n" +
|
||||
".field public static field1:Ljava/lang/reflect/Field; = LHelloWorld;->someField:I\n" +
|
||||
".field public static field2:Ljava/lang/reflect/Field; = LHelloWorld;->V:I\n" +
|
||||
".field public static field3:Ljava/lang/reflect/Field; = LHelloWorld;->I:I";
|
||||
|
||||
String expected = "" +
|
||||
".class public LHelloWorld;\n" +
|
||||
".super Ljava/lang/Object;\n" +
|
||||
"# static fields\n" +
|
||||
".field public static field1:Ljava/lang/reflect/Field; = LHelloWorld;->someField:I\n" +
|
||||
".field public static field2:Ljava/lang/reflect/Field; = LHelloWorld;->V:I\n" +
|
||||
".field public static field3:Ljava/lang/reflect/Field; = LHelloWorld;->I:I\n";
|
||||
|
||||
baksmaliOptions options = new baksmaliOptions();
|
||||
options.useImplicitReferences = false;
|
||||
|
||||
BaksmaliTestUtils.assertSmaliCompiledEquals(source, expected, options);
|
||||
}
|
||||
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class InterfaceOrderTest extends IdenticalRoundtripTest {
|
||||
@Test
|
||||
public void testInterfaceOrder() {
|
||||
runTest("InterfaceOrder", new baksmaliOptions());
|
||||
}
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class LambdaTest extends IdenticalRoundtripTest {
|
||||
|
||||
private baksmaliOptions createOptions() {
|
||||
baksmaliOptions options = new baksmaliOptions();
|
||||
options.apiLevel = 23; // since we need at least level 23 for lambda opcodes
|
||||
options.experimental = true; // since these opcodes aren't implemented in runtime yet);
|
||||
return options;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHelloWorldLambda() {
|
||||
runTest("HelloWorldLambda", createOptions());
|
||||
}
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class ManyRegistersTest extends IdenticalRoundtripTest {
|
||||
|
||||
@Test
|
||||
public void testManyRegisters() {
|
||||
runTest("ManyRegisters");
|
||||
}
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class MultiSwitchTest extends DisassemblyTest {
|
||||
|
||||
@Test
|
||||
public void testMultiSwitch() {
|
||||
runTest("MultiSwitch");
|
||||
}
|
||||
}
|
@ -1,95 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali;
|
||||
|
||||
import org.antlr.runtime.RecognitionException;
|
||||
import org.junit.Assert;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* A base test class for performing a roundtrip assembly/disassembly
|
||||
*
|
||||
* The test accepts a smali file as input, performs a smali -> dex -> smali roundtrip, and
|
||||
* verifies that the result equals a known-good output smali file.
|
||||
*
|
||||
* By default, the input and output files should be resources at [testDir]/[testName]Input.smali
|
||||
* and [testDir]/[testName]Output.smali respectively
|
||||
*/
|
||||
public abstract class RoundtripTest {
|
||||
protected final String testDir;
|
||||
|
||||
protected RoundtripTest(@Nonnull String testDir) {
|
||||
this.testDir = testDir;
|
||||
}
|
||||
|
||||
protected RoundtripTest() {
|
||||
this.testDir = this.getClass().getSimpleName();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
protected String getInputFilename(@Nonnull String testName) {
|
||||
return String.format("%s%s%sInput.smali", testDir, File.separatorChar, testName);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
protected String getOutputFilename(@Nonnull String testName) {
|
||||
return String.format("%s%s%sOutput.smali", testDir, File.separatorChar, testName);
|
||||
}
|
||||
|
||||
protected void runTest(@Nonnull String testName) {
|
||||
runTest(testName, new baksmaliOptions());
|
||||
}
|
||||
|
||||
protected void runTest(@Nonnull String testName, @Nonnull baksmaliOptions options) {
|
||||
try {
|
||||
// Load file from resources as a stream
|
||||
String inputFilename = getInputFilename(testName);
|
||||
String input = BaksmaliTestUtils.readResourceFully(getInputFilename(testName));
|
||||
String output;
|
||||
if (getOutputFilename(testName).equals(inputFilename)) {
|
||||
output = input;
|
||||
} else {
|
||||
output = BaksmaliTestUtils.readResourceFully(getOutputFilename(testName));
|
||||
}
|
||||
|
||||
// Run smali, baksmali, and then compare strings are equal (minus comments/whitespace)
|
||||
BaksmaliTestUtils.assertSmaliCompiledEquals(input, output, options, true);
|
||||
} catch (IOException ex) {
|
||||
Assert.fail();
|
||||
} catch (RecognitionException ex) {
|
||||
Assert.fail();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.baksmali;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class SwitchTest extends RoundtripTest {
|
||||
@Test
|
||||
public void testUnorderedSparseSwitch() {
|
||||
runTest("UnorderedSparseSwitch");
|
||||
}
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
.class public LConstructorTest;
|
||||
.super Ljava/lang/Object;
|
||||
|
||||
|
||||
# direct methods
|
||||
.method public constructor <init>()V
|
||||
.registers 4
|
||||
|
||||
#v0=(Uninit);v1=(Uninit);v2=(Uninit);p0=(UninitThis,LConstructorTest;);
|
||||
invoke-direct {p0}, Ljava/lang/Object;-><init>()V
|
||||
#v0=(Uninit);v1=(Uninit);v2=(Uninit);p0=(Reference,LConstructorTest;);
|
||||
|
||||
#v0=(Uninit);v1=(Uninit);v2=(Uninit);p0=(Reference,LConstructorTest;);
|
||||
return-void
|
||||
#v0=(Uninit);v1=(Uninit);v2=(Uninit);p0=(Reference,LConstructorTest;);
|
||||
.end method
|
@ -1,25 +0,0 @@
|
||||
.class public LConstructorTest2;
|
||||
.super Ljava/lang/Object;
|
||||
|
||||
|
||||
# direct methods
|
||||
.method public constructor <init>()V
|
||||
.registers 4
|
||||
|
||||
#v0=(Uninit);v1=(Uninit);v2=(Uninit);p0=(UninitThis,LConstructorTest2;);
|
||||
if-eqz p0, :cond_3
|
||||
#v0=(Uninit);v1=(Uninit);v2=(Uninit);p0=(UninitThis,LConstructorTest2;);
|
||||
|
||||
#v0=(Uninit);v1=(Uninit);v2=(Uninit);p0=(UninitThis,LConstructorTest2;);
|
||||
nop
|
||||
#v0=(Uninit);v1=(Uninit);v2=(Uninit);p0=(UninitThis,LConstructorTest2;);
|
||||
|
||||
:cond_3
|
||||
#v0=(Uninit);v1=(Uninit);v2=(Uninit);p0=(UninitThis,LConstructorTest2;);
|
||||
invoke-direct {p0}, Ljava/lang/Object;-><init>()V
|
||||
#v0=(Uninit);v1=(Uninit);v2=(Uninit);p0=(Reference,LConstructorTest2;);
|
||||
|
||||
#v0=(Uninit);v1=(Uninit);v2=(Uninit);p0=(Reference,LConstructorTest2;);
|
||||
return-void
|
||||
#v0=(Uninit);v1=(Uninit);v2=(Uninit);p0=(Reference,LConstructorTest2;);
|
||||
.end method
|
Binary file not shown.
@ -1,29 +0,0 @@
|
||||
.class public LDuplicateDirectMethods;
|
||||
.super Ljava/lang/Object;
|
||||
|
||||
|
||||
# direct methods
|
||||
.method private alah()V
|
||||
.registers 1
|
||||
|
||||
return-void
|
||||
.end method
|
||||
|
||||
.method private blah()V
|
||||
.registers 1
|
||||
|
||||
return-void
|
||||
.end method
|
||||
|
||||
# duplicate method ignored
|
||||
# .method private blah()V
|
||||
# .registers 1
|
||||
|
||||
# return-void
|
||||
# .end method
|
||||
|
||||
.method private clah()V
|
||||
.registers 1
|
||||
|
||||
return-void
|
||||
.end method
|
@ -1,46 +0,0 @@
|
||||
.class public LDuplicateDirectVirtualMethods;
|
||||
.super Ljava/lang/Object;
|
||||
|
||||
|
||||
# direct methods
|
||||
.method private blah()V
|
||||
.registers 1
|
||||
|
||||
return-void
|
||||
.end method
|
||||
|
||||
# duplicate method ignored
|
||||
# .method private blah()V
|
||||
# .registers 1
|
||||
|
||||
# return-void
|
||||
# .end method
|
||||
|
||||
|
||||
# virtual methods
|
||||
.method public alah()V
|
||||
.registers 1
|
||||
|
||||
return-void
|
||||
.end method
|
||||
|
||||
# There is both a direct and virtual method with this signature.
|
||||
# You will need to rename one of these methods, including all references.
|
||||
.method public blah()V
|
||||
.registers 1
|
||||
|
||||
return-void
|
||||
.end method
|
||||
|
||||
# duplicate method ignored
|
||||
# .method public blah()V
|
||||
# .registers 1
|
||||
|
||||
# return-void
|
||||
# .end method
|
||||
|
||||
.method public clah()V
|
||||
.registers 1
|
||||
|
||||
return-void
|
||||
.end method
|
@ -1,13 +0,0 @@
|
||||
.class public LDuplicateInstanceFields;
|
||||
.super Ljava/lang/Object;
|
||||
|
||||
|
||||
# instance fields
|
||||
.field public alah:I
|
||||
|
||||
.field public blah:I
|
||||
|
||||
# duplicate field ignored
|
||||
# .field public blah:I
|
||||
|
||||
.field public clah:I
|
@ -1,13 +0,0 @@
|
||||
.class public LDuplicateStaticFields;
|
||||
.super Ljava/lang/Object;
|
||||
|
||||
|
||||
# static fields
|
||||
.field public static alah:I
|
||||
|
||||
.field public static blah:I
|
||||
|
||||
# duplicate field ignored
|
||||
# .field public static blah:I
|
||||
|
||||
.field public static clah:I
|
@ -1,22 +0,0 @@
|
||||
.class public LDuplicateStaticInstanceFields;
|
||||
.super Ljava/lang/Object;
|
||||
|
||||
|
||||
# static fields
|
||||
.field public static blah:I
|
||||
|
||||
# duplicate field ignored
|
||||
# .field public static blah:I
|
||||
|
||||
|
||||
# instance fields
|
||||
.field public alah:I
|
||||
|
||||
# There is both a static and instance field with this signature.
|
||||
# You will need to rename one of these fields, including all references.
|
||||
.field public blah:I
|
||||
|
||||
# duplicate field ignored
|
||||
# .field public blah:I
|
||||
|
||||
.field public clah:I
|
@ -1,29 +0,0 @@
|
||||
.class public LDuplicateVirtualMethods;
|
||||
.super Ljava/lang/Object;
|
||||
|
||||
|
||||
# virtual methods
|
||||
.method public alah()V
|
||||
.registers 1
|
||||
|
||||
return-void
|
||||
.end method
|
||||
|
||||
.method public blah()V
|
||||
.registers 1
|
||||
|
||||
return-void
|
||||
.end method
|
||||
|
||||
# duplicate method ignored
|
||||
# .method public blah()V
|
||||
# .registers 1
|
||||
|
||||
# return-void
|
||||
# .end method
|
||||
|
||||
.method public clah()V
|
||||
.registers 1
|
||||
|
||||
return-void
|
||||
.end method
|
Binary file not shown.
@ -1,22 +0,0 @@
|
||||
.class public LDuplicateDirectMethods;
|
||||
.super Ljava/lang/Object;
|
||||
|
||||
.method private alah()V
|
||||
.registers 1
|
||||
return-void
|
||||
.end method
|
||||
|
||||
.method private blah()V
|
||||
.registers 1
|
||||
return-void
|
||||
.end method
|
||||
|
||||
.method private blah()V
|
||||
.registers 1
|
||||
return-void
|
||||
.end method
|
||||
|
||||
.method private clah()V
|
||||
.registers 1
|
||||
return-void
|
||||
.end method
|
@ -1,32 +0,0 @@
|
||||
.class public LDuplicateDirectVirtualMethods;
|
||||
.super Ljava/lang/Object;
|
||||
|
||||
.method public alah()V
|
||||
.registers 1
|
||||
return-void
|
||||
.end method
|
||||
|
||||
.method private blah()V
|
||||
.registers 1
|
||||
return-void
|
||||
.end method
|
||||
|
||||
.method private blah()V
|
||||
.registers 1
|
||||
return-void
|
||||
.end method
|
||||
|
||||
.method public blah()V
|
||||
.registers 1
|
||||
return-void
|
||||
.end method
|
||||
|
||||
.method public blah()V
|
||||
.registers 1
|
||||
return-void
|
||||
.end method
|
||||
|
||||
.method public clah()V
|
||||
.registers 1
|
||||
return-void
|
||||
.end method
|
@ -1,9 +0,0 @@
|
||||
.class public LDuplicateInstanceFields;
|
||||
.super Ljava/lang/Object;
|
||||
|
||||
.field public alah:I
|
||||
|
||||
.field public blah:I
|
||||
.field public blah:I
|
||||
|
||||
.field public clah:I
|
@ -1,9 +0,0 @@
|
||||
.class public LDuplicateStaticFields;
|
||||
.super Ljava/lang/Object;
|
||||
|
||||
.field public static alah:I
|
||||
|
||||
.field public static blah:I
|
||||
.field public static blah:I
|
||||
|
||||
.field public static clah:I
|
@ -1,11 +0,0 @@
|
||||
.class public LDuplicateStaticInstanceFields;
|
||||
.super Ljava/lang/Object;
|
||||
|
||||
.field public alah:I
|
||||
|
||||
.field public blah:I
|
||||
.field public blah:I
|
||||
.field static public blah:I
|
||||
.field static public blah:I
|
||||
|
||||
.field public clah:I
|
@ -1,22 +0,0 @@
|
||||
.class public LDuplicateVirtualMethods;
|
||||
.super Ljava/lang/Object;
|
||||
|
||||
.method public alah()V
|
||||
.registers 1
|
||||
return-void
|
||||
.end method
|
||||
|
||||
.method public blah()V
|
||||
.registers 1
|
||||
return-void
|
||||
.end method
|
||||
|
||||
.method public blah()V
|
||||
.registers 1
|
||||
return-void
|
||||
.end method
|
||||
|
||||
.method public clah()V
|
||||
.registers 1
|
||||
return-void
|
||||
.end method
|
@ -1,3 +0,0 @@
|
||||
The test dex file was produced from these smali files, using
|
||||
an old version of smali that doesn't check for field/method
|
||||
duplicates
|
@ -1,37 +0,0 @@
|
||||
.class public LInterfaceOrder;
|
||||
.super Ljava/lang/Object;
|
||||
|
||||
# Note how these two interfaces are not in alphabetical order
|
||||
.implements Ljava/io/Serializable;
|
||||
.implements Ljava/util/EventListener;
|
||||
.implements Ljava/lang/Runnable;
|
||||
.implements Ljava/io/Flushable;
|
||||
.implements Ljava/lang/Clonable;
|
||||
.implements Ljava/util/Observer;
|
||||
.implements Ljava/io/Closeable;
|
||||
|
||||
# direct methods
|
||||
.method public constructor <init>()V
|
||||
.registers 1
|
||||
return-void
|
||||
.end method
|
||||
|
||||
.method public close()V
|
||||
.registers 1
|
||||
return-void
|
||||
.end method
|
||||
|
||||
.method public flush()V
|
||||
.registers 1
|
||||
return-void
|
||||
.end method
|
||||
|
||||
.method public run()V
|
||||
.registers 1
|
||||
return-void
|
||||
.end method
|
||||
|
||||
.method public update(Ljava/util/Observable;Ljava/lang/Object;)V
|
||||
.registers 3
|
||||
return-void
|
||||
.end method
|
@ -1,55 +0,0 @@
|
||||
.class public LHelloWorldLambda;
|
||||
|
||||
#Ye olde hello world application (with lambdas!)
|
||||
#To assemble and run this on a phone or emulator:
|
||||
#
|
||||
#java -jar smali.jar -o classes.dex HelloWorldLambda.smali HelloWorldFunctionalInterface.smali
|
||||
#zip HelloWorld.zip classes.dex
|
||||
#adb push HelloWorld.zip /data/local
|
||||
#adb shell dalvikvm -cp /data/local/HelloWorld.zip HelloWorld
|
||||
#
|
||||
#if you get out of memory type errors when running smali.jar, try
|
||||
#java -Xmx512m -jar smali.jar HelloWorldLambda.smali
|
||||
#instead
|
||||
|
||||
.super Ljava/lang/Object;
|
||||
|
||||
.method public static doHelloWorld(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
|
||||
.registers 6 # 4 parameters, 2 locals
|
||||
liberate-variable v0, p0, "helloworld"
|
||||
|
||||
sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
|
||||
invoke-virtual {v1, v0}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
|
||||
|
||||
return-void
|
||||
.end method
|
||||
|
||||
.method public static main([Ljava/lang/String;)V
|
||||
.registers 9 # 1 parameter, 8 locals
|
||||
|
||||
sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream;
|
||||
|
||||
const-string v1, "Hello World!"
|
||||
const-string v2, "How" # vD
|
||||
const-string v3, "are" # vE
|
||||
const-string v4, "you" # vF
|
||||
const-string v5, "doing?" # vG
|
||||
|
||||
capture-variable v1, "helloworld"
|
||||
|
||||
# TODO: do I need to pass the type of the lambda's functional interface here as a type id?
|
||||
create-lambda v1, LHelloWorldLambda;->doHelloWorld(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
|
||||
# Method descriptor is not required here, because only the single-abstract method is ever invoked.
|
||||
invoke-lambda v1, {v2, v3, v4, v5}
|
||||
|
||||
box-lambda v6, v1
|
||||
invoke-virtual {v6, v2, v3, v4, v5}, LHelloWorldFunctionalInterface;->applyFourStrings(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
|
||||
|
||||
# FIXME: should be \HelloWorldFunctionalInterface; instead of L...;
|
||||
|
||||
# TODO: do we really need the type descriptor here at all?
|
||||
unbox-lambda v7, v6, LHelloWorldFunctionalInterface;
|
||||
invoke-lambda v7, {v2, v3, v4, v5}
|
||||
|
||||
return-void
|
||||
.end method
|
@ -1,31 +0,0 @@
|
||||
.class public LLocalTest;
|
||||
.super Ljava/lang/Object;
|
||||
|
||||
|
||||
# direct methods
|
||||
.method public static method1()V
|
||||
.registers 10
|
||||
|
||||
.local v0, "blah! This local name has some spaces, a colon, even a \nnewline!":I, "some sig info:\nblah."
|
||||
.local v1, "blah! This local name has some spaces, a colon, even a \nnewline!":V, "some sig info:\nblah."
|
||||
.local v2, "blah! This local name has some spaces, a colon, even a \nnewline!":I
|
||||
.local v3, "blah! This local name has some spaces, a colon, even a \nnewline!":V
|
||||
.local v4, null:I, "some sig info:\nblah."
|
||||
.local v5, null:V, "some sig info:\nblah."
|
||||
.local v6, null:I
|
||||
.local v7
|
||||
.local v8
|
||||
.local v9
|
||||
return-void
|
||||
.end method
|
||||
|
||||
.method public static method2(IJLjava/lang/String;)V
|
||||
.registers 10
|
||||
.param p0, "blah! This local name has some spaces, a colon, even a \nnewline!" # I
|
||||
.param p1 # J
|
||||
.annotation runtime LAnnotationWithValues;
|
||||
.end annotation
|
||||
.end param
|
||||
|
||||
return-void
|
||||
.end method
|
Binary file not shown.
@ -1,7 +0,0 @@
|
||||
.class LManyRegisters;
|
||||
.super Ljava/lang/Object;
|
||||
|
||||
.method public manyRegisters()V
|
||||
.registers 65535
|
||||
return-void
|
||||
.end method
|
Binary file not shown.
@ -1,72 +0,0 @@
|
||||
.class public LMultiSwitch;
|
||||
.super Ljava/lang/Object;
|
||||
.source "Format31t.smali"
|
||||
|
||||
.method public multi-packed-switch()V
|
||||
.registers 1
|
||||
const p0, 0xc
|
||||
packed-switch p0, :pswitch_data_12
|
||||
goto :goto_b
|
||||
:pswitch_7
|
||||
return-void
|
||||
:pswitch_8
|
||||
return-void
|
||||
:pswitch_9
|
||||
return-void
|
||||
:pswitch_a
|
||||
return-void
|
||||
:goto_b
|
||||
packed-switch p0, :pswitch_data_12
|
||||
nop
|
||||
return-void
|
||||
:pswitch_f
|
||||
return-void
|
||||
:pswitch_10
|
||||
return-void
|
||||
:pswitch_11
|
||||
return-void
|
||||
:pswitch_12
|
||||
:pswitch_data_12
|
||||
.packed-switch 0xa
|
||||
:pswitch_7
|
||||
:pswitch_8
|
||||
:pswitch_9
|
||||
:pswitch_a
|
||||
.end packed-switch
|
||||
|
||||
.end method
|
||||
|
||||
.method public multi-sparse-switch()V
|
||||
.registers 1
|
||||
const p0, 0xd
|
||||
sparse-switch p0, :sswitch_data_12
|
||||
goto :goto_b
|
||||
:sswitch_7
|
||||
return-void
|
||||
:sswitch_8
|
||||
return-void
|
||||
:sswitch_9
|
||||
return-void
|
||||
:sswitch_a
|
||||
return-void
|
||||
:goto_b
|
||||
sparse-switch p0, :sswitch_data_12
|
||||
nop
|
||||
return-void
|
||||
:sswitch_f
|
||||
return-void
|
||||
:sswitch_10
|
||||
return-void
|
||||
:sswitch_11
|
||||
return-void
|
||||
|
||||
:sswitch_12
|
||||
|
||||
:sswitch_data_12
|
||||
.sparse-switch
|
||||
0xa -> :sswitch_7
|
||||
0xf -> :sswitch_9
|
||||
0x14 -> :sswitch_8
|
||||
0x63 -> :sswitch_a
|
||||
.end sparse-switch
|
||||
.end method
|
@ -1,119 +0,0 @@
|
||||
.class public LMultiSwitch;
|
||||
.super Ljava/lang/Object;
|
||||
.source "Format31t.smali"
|
||||
|
||||
|
||||
# virtual methods
|
||||
.method public multi-packed-switch()V
|
||||
.registers 1
|
||||
|
||||
const p0, 0xc
|
||||
|
||||
packed-switch p0, :pswitch_data_14
|
||||
|
||||
goto :goto_b
|
||||
|
||||
:pswitch_7
|
||||
return-void
|
||||
|
||||
:pswitch_8
|
||||
return-void
|
||||
|
||||
:pswitch_9
|
||||
return-void
|
||||
|
||||
:pswitch_a
|
||||
return-void
|
||||
|
||||
:goto_b
|
||||
packed-switch p0, :pswitch_data_20
|
||||
|
||||
nop
|
||||
|
||||
:pswitch_f
|
||||
return-void
|
||||
|
||||
:pswitch_10
|
||||
return-void
|
||||
|
||||
:pswitch_11
|
||||
return-void
|
||||
|
||||
:pswitch_12
|
||||
return-void
|
||||
|
||||
nop
|
||||
|
||||
:pswitch_data_14
|
||||
.packed-switch 0xa
|
||||
:pswitch_7
|
||||
:pswitch_8
|
||||
:pswitch_9
|
||||
:pswitch_a
|
||||
.end packed-switch
|
||||
|
||||
:pswitch_data_20
|
||||
.packed-switch 0xa
|
||||
:pswitch_f
|
||||
:pswitch_10
|
||||
:pswitch_11
|
||||
:pswitch_12
|
||||
.end packed-switch
|
||||
.end method
|
||||
|
||||
.method public multi-sparse-switch()V
|
||||
.registers 1
|
||||
|
||||
const p0, 0xd
|
||||
|
||||
sparse-switch p0, :sswitch_data_14
|
||||
|
||||
goto :goto_b
|
||||
|
||||
:sswitch_7
|
||||
return-void
|
||||
|
||||
:sswitch_8
|
||||
return-void
|
||||
|
||||
:sswitch_9
|
||||
return-void
|
||||
|
||||
:sswitch_a
|
||||
return-void
|
||||
|
||||
:goto_b
|
||||
sparse-switch p0, :sswitch_data_26
|
||||
|
||||
nop
|
||||
|
||||
:sswitch_f
|
||||
return-void
|
||||
|
||||
:sswitch_10
|
||||
return-void
|
||||
|
||||
:sswitch_11
|
||||
return-void
|
||||
|
||||
:sswitch_12
|
||||
return-void
|
||||
|
||||
nop
|
||||
|
||||
:sswitch_data_14
|
||||
.sparse-switch
|
||||
0xa -> :sswitch_7
|
||||
0xf -> :sswitch_9
|
||||
0x14 -> :sswitch_8
|
||||
0x63 -> :sswitch_a
|
||||
.end sparse-switch
|
||||
|
||||
:sswitch_data_26
|
||||
.sparse-switch
|
||||
0xa -> :sswitch_f
|
||||
0xf -> :sswitch_11
|
||||
0x14 -> :sswitch_10
|
||||
0x63 -> :sswitch_12
|
||||
.end sparse-switch
|
||||
.end method
|
@ -1,46 +0,0 @@
|
||||
.class public LMultipleStartInstructionsTest;
|
||||
.super Ljava/lang/Object;
|
||||
|
||||
|
||||
# direct methods
|
||||
.method public constructor <init>(Ljava/lang/String;)V
|
||||
.registers 4
|
||||
|
||||
:try_start_0
|
||||
#v0=(Uninit);v1=(Uninit);p0=(UninitThis,LMultipleStartInstructionsTest;);p1=(Reference,Ljava/lang/String;);
|
||||
invoke-direct {p0}, Ljava/lang/Object;-><init>()V
|
||||
#v0=(Uninit);v1=(Uninit);p0=(Reference,LMultipleStartInstructionsTest;);p1=(Reference,Ljava/lang/String;);
|
||||
|
||||
#v0=(Uninit);v1=(Uninit);p0=(Reference,LMultipleStartInstructionsTest;);p1=(Reference,Ljava/lang/String;);
|
||||
const-string v0, "blah"
|
||||
#v0=(Reference,Ljava/lang/String;);v1=(Uninit);p0=(Reference,LMultipleStartInstructionsTest;);p1=(Reference,Ljava/lang/String;);
|
||||
|
||||
#v0=(Reference,Ljava/lang/String;);v1=(Uninit);p0=(Reference,LMultipleStartInstructionsTest;);p1=(Reference,Ljava/lang/String;);
|
||||
return-void
|
||||
#v0=(Reference,Ljava/lang/String;);v1=(Uninit);p0=(Reference,LMultipleStartInstructionsTest;);p1=(Reference,Ljava/lang/String;);
|
||||
:try_end_6
|
||||
.catchall {:try_start_0 .. :try_end_6} :catchall_6
|
||||
|
||||
:catchall_6
|
||||
:try_start_6
|
||||
#v0=(Uninit);v1=(Uninit);
|
||||
#p0=(Conflicted):merge{Start:(UninitThis,LMultipleStartInstructionsTest;),0x0:(Reference,LMultipleStartInstructionsTest;)}
|
||||
#p1=(Reference,Ljava/lang/String;);
|
||||
invoke-static {}, LMultipleStartInstructionsTest;->blah()V
|
||||
#v0=(Uninit);v1=(Uninit);p0=(Conflicted);p1=(Reference,Ljava/lang/String;);
|
||||
:try_end_9
|
||||
.catchall {:try_start_6 .. :try_end_9} :catchall_9
|
||||
|
||||
:catchall_9
|
||||
#v0=(Uninit);v1=(Uninit);
|
||||
#p0=(Conflicted):merge{Start:(UninitThis,LMultipleStartInstructionsTest;),0x0:(Reference,LMultipleStartInstructionsTest;),0x6:(Conflicted)}
|
||||
#p1=(Reference,Ljava/lang/String;);
|
||||
return-void
|
||||
#v0=(Uninit);v1=(Uninit);p0=(Conflicted);p1=(Reference,Ljava/lang/String;);
|
||||
.end method
|
||||
|
||||
.method public static blah()V
|
||||
.registers 0
|
||||
|
||||
return-void
|
||||
.end method
|
Binary file not shown.
@ -1,37 +0,0 @@
|
||||
.class public LRegisterEqualityOnMerge;
|
||||
.super Ljava/lang/Object;
|
||||
|
||||
|
||||
# direct methods
|
||||
.method public constructor <init>()V
|
||||
.registers 4
|
||||
|
||||
#v0=(Uninit);v1=(Uninit);v2=(Uninit);p0=(UninitThis,LRegisterEqualityOnMerge;);
|
||||
invoke-direct {p0}, Ljava/lang/Object;-><init>()V
|
||||
#v0=(Uninit);v1=(Uninit);v2=(Uninit);p0=(Reference,LRegisterEqualityOnMerge;);
|
||||
|
||||
#v0=(Uninit);v1=(Uninit);v2=(Uninit);p0=(Reference,LRegisterEqualityOnMerge;);
|
||||
invoke-virtual {p0}, Ljava/lang/Object;->toString()Ljava/lang/String;
|
||||
#v0=(Uninit);v1=(Uninit);v2=(Uninit);p0=(Reference,LRegisterEqualityOnMerge;);
|
||||
|
||||
#v0=(Uninit);v1=(Uninit);v2=(Uninit);p0=(Reference,LRegisterEqualityOnMerge;);
|
||||
move-result-object v0
|
||||
#v0=(Reference,Ljava/lang/String;);v1=(Uninit);v2=(Uninit);p0=(Reference,LRegisterEqualityOnMerge;);
|
||||
|
||||
#v0=(Reference,Ljava/lang/String;);v1=(Uninit);v2=(Uninit);p0=(Reference,LRegisterEqualityOnMerge;);
|
||||
if-eqz v0, :cond_d
|
||||
#v0=(Reference,Ljava/lang/String;);v1=(Uninit);v2=(Uninit);p0=(Reference,LRegisterEqualityOnMerge;);
|
||||
|
||||
#v0=(Reference,Ljava/lang/String;);v1=(Uninit);v2=(Uninit);p0=(Reference,LRegisterEqualityOnMerge;);
|
||||
invoke-virtual {p0}, Ljava/lang/Object;->toString()Ljava/lang/String;
|
||||
#v0=(Reference,Ljava/lang/String;);v1=(Uninit);v2=(Uninit);p0=(Reference,LRegisterEqualityOnMerge;);
|
||||
|
||||
#v0=(Reference,Ljava/lang/String;);v1=(Uninit);v2=(Uninit);p0=(Reference,LRegisterEqualityOnMerge;);
|
||||
move-result-object v0
|
||||
#v0=(Reference,Ljava/lang/String;);v1=(Uninit);v2=(Uninit);p0=(Reference,LRegisterEqualityOnMerge;);
|
||||
|
||||
:cond_d
|
||||
#v0=(Reference,Ljava/lang/String;);v1=(Uninit);v2=(Uninit);p0=(Reference,LRegisterEqualityOnMerge;);
|
||||
return-void
|
||||
#v0=(Reference,Ljava/lang/String;);v1=(Uninit);v2=(Uninit);p0=(Reference,LRegisterEqualityOnMerge;);
|
||||
.end method
|
Binary file not shown.
@ -1,35 +0,0 @@
|
||||
.class public LUnorderedSparseSwitch;
|
||||
.super Ljava/lang/Object;
|
||||
|
||||
.method public static test_sparse-switch()V
|
||||
.registers 1
|
||||
|
||||
const v0, 13
|
||||
|
||||
sparse-switch v0, :SparseSwitch
|
||||
|
||||
:Label10
|
||||
return-void
|
||||
|
||||
:Label20
|
||||
return-void
|
||||
|
||||
:Label15
|
||||
return-void
|
||||
|
||||
:Label13
|
||||
return-void
|
||||
|
||||
:Label99
|
||||
return-void
|
||||
|
||||
# Note: unordered keys
|
||||
:SparseSwitch
|
||||
.sparse-switch
|
||||
10 -> :Label10
|
||||
20 -> :Label20
|
||||
15 -> :Label15
|
||||
99 -> :Label99
|
||||
13 -> :Label13
|
||||
.end sparse-switch
|
||||
.end method
|
@ -1,28 +0,0 @@
|
||||
.class public LUnorderedSparseSwitch;
|
||||
.super Ljava/lang/Object;
|
||||
.method public static test_sparse-switch()V
|
||||
.registers 1
|
||||
const v0, 0xd
|
||||
sparse-switch v0, :sswitch_data_c
|
||||
:sswitch_6
|
||||
return-void
|
||||
:sswitch_7
|
||||
return-void
|
||||
:sswitch_8
|
||||
return-void
|
||||
:sswitch_9
|
||||
return-void
|
||||
:sswitch_a
|
||||
return-void
|
||||
nop
|
||||
|
||||
# Note: ordered keys
|
||||
:sswitch_data_c
|
||||
.sparse-switch
|
||||
0xa -> :sswitch_6
|
||||
0xd -> :sswitch_9
|
||||
0xf -> :sswitch_8
|
||||
0x14 -> :sswitch_7
|
||||
0x63 -> :sswitch_a
|
||||
.end sparse-switch
|
||||
.end method
|
@ -1,50 +0,0 @@
|
||||
.class public LUninitRefIdentityTest;
|
||||
.super Ljava/lang/Object;
|
||||
|
||||
|
||||
# direct methods
|
||||
.method public constructor <init>()V
|
||||
.registers 4
|
||||
|
||||
#v0=(Uninit);v1=(Uninit);v2=(Uninit);p0=(UninitThis,LUninitRefIdentityTest;);
|
||||
invoke-direct {p0}, Ljava/lang/Object;-><init>()V
|
||||
#v0=(Uninit);v1=(Uninit);v2=(Uninit);p0=(Reference,LUninitRefIdentityTest;);
|
||||
|
||||
#v0=(Uninit);v1=(Uninit);v2=(Uninit);p0=(Reference,LUninitRefIdentityTest;);
|
||||
new-instance v0, Ljava/lang/String;
|
||||
#v0=(UninitRef,Ljava/lang/String;);v1=(Uninit);v2=(Uninit);p0=(Reference,LUninitRefIdentityTest;);
|
||||
|
||||
#v0=(UninitRef,Ljava/lang/String;);v1=(Uninit);v2=(Uninit);p0=(Reference,LUninitRefIdentityTest;);
|
||||
if-eqz v0, :cond_9
|
||||
#v0=(UninitRef,Ljava/lang/String;);v1=(Uninit);v2=(Uninit);p0=(Reference,LUninitRefIdentityTest;);
|
||||
|
||||
#v0=(UninitRef,Ljava/lang/String;);v1=(Uninit);v2=(Uninit);p0=(Reference,LUninitRefIdentityTest;);
|
||||
new-instance v0, Ljava/lang/String;
|
||||
#v0=(UninitRef,Ljava/lang/String;);v1=(Uninit);v2=(Uninit);p0=(Reference,LUninitRefIdentityTest;);
|
||||
|
||||
:cond_9
|
||||
#v0=(Conflicted):merge{0x5:(UninitRef,Ljava/lang/String;),0x7:(UninitRef,Ljava/lang/String;)}
|
||||
#v1=(Uninit);v2=(Uninit);p0=(Reference,LUninitRefIdentityTest;);
|
||||
invoke-direct {v0}, Ljava/lang/String;-><init>()V
|
||||
#v0=(Unknown);v1=(Uninit);v2=(Uninit);p0=(Reference,LUninitRefIdentityTest;);
|
||||
|
||||
#v0=(Unknown);v1=(Uninit);v2=(Uninit);p0=(Reference,LUninitRefIdentityTest;);
|
||||
return-void
|
||||
#v0=(Unknown);v1=(Uninit);v2=(Uninit);p0=(Reference,LUninitRefIdentityTest;);
|
||||
.end method
|
||||
|
||||
.method public constructor <init>(Ljava/lang/String;)V
|
||||
.registers 2
|
||||
|
||||
#p0=(UninitThis,LUninitRefIdentityTest;);p1=(Reference,Ljava/lang/String;);
|
||||
move-object p1, p0
|
||||
#p0=(UninitThis,LUninitRefIdentityTest;);p1=(UninitThis,LUninitRefIdentityTest;);
|
||||
|
||||
#p0=(UninitThis,LUninitRefIdentityTest;);p1=(UninitThis,LUninitRefIdentityTest;);
|
||||
invoke-direct {p0}, Ljava/lang/Object;-><init>()V
|
||||
#p0=(Reference,LUninitRefIdentityTest;);p1=(Reference,LUninitRefIdentityTest;);
|
||||
|
||||
#p0=(Reference,LUninitRefIdentityTest;);p1=(Reference,LUninitRefIdentityTest;);
|
||||
return-void
|
||||
#p0=(Reference,LUninitRefIdentityTest;);p1=(Reference,LUninitRefIdentityTest;);
|
||||
.end method
|
Binary file not shown.
@ -1,218 +0,0 @@
|
||||
.class public Lbaksmali/test/class;
|
||||
.super Ljava/lang/Object;
|
||||
|
||||
.source "baksmali_test_class.smali"
|
||||
|
||||
.implements Lsome/interface;
|
||||
.implements Lsome/other/interface;
|
||||
|
||||
|
||||
.annotation build Lsome/annotation;
|
||||
value1 = "test"
|
||||
value2 = .subannotation Lsome/annotation;
|
||||
value1 = "test2"
|
||||
value2 = Lsome/enum;
|
||||
.end subannotation
|
||||
.end annotation
|
||||
|
||||
.annotation system Lsome/annotation;
|
||||
.end annotation
|
||||
|
||||
|
||||
|
||||
.field public static aStaticFieldWithoutAnInitializer:I
|
||||
|
||||
.field public static longStaticField:J = 0x300000000L
|
||||
.field public static longNegStaticField:J = -0x300000000L
|
||||
|
||||
.field public static intStaticField:I = 0x70000000
|
||||
.field public static intNegStaticField:I = -500
|
||||
|
||||
.field public static shortStaticField:S = 500s
|
||||
.field public static shortNegStaticField:S = -500s
|
||||
|
||||
.field public static byteStaticField:B = 123t
|
||||
.field public static byteNegStaticField:B = 0xAAt
|
||||
|
||||
.field public static floatStaticField:F = 3.1415926f
|
||||
|
||||
.field public static doubleStaticField:D = 3.141592653589793
|
||||
|
||||
.field public static charStaticField:C = 'a'
|
||||
.field public static charEscapedStaticField:C = '\n'
|
||||
|
||||
.field public static boolTrueStaticField:Z = true
|
||||
.field public static boolFalseStaticField:Z = false
|
||||
|
||||
.field public static typeStaticField:Ljava/lang/Class; = Lbaksmali/test/class;
|
||||
|
||||
.field public static stringStaticField:Ljava/lang/String; = "test"
|
||||
.field public static stringEscapedStaticField:Ljava/lang/String; = "test\ntest"
|
||||
|
||||
|
||||
.field public static fieldStaticField:Ljava/lang/reflect/Field; = Lbaksmali/test/class;->fieldStaticField:Ljava/lang/reflect/Field;
|
||||
|
||||
.field public static methodStaticField:Ljava/lang/reflect/Method; = Lbaksmali/test/class;->teshMethod(ILjava/lang/String;)Ljava/lang/String;
|
||||
|
||||
.field public static arrayStaticField:[I = {1, 2, 3, {1, 2, 3, 4}}
|
||||
|
||||
.field public static enumStaticField:Lsome/enum; = .enum Lsome/enum;->someEnumValue:Lsome/enum;
|
||||
|
||||
.field public static annotationStaticField:Lsome/annotation; = .subannotation Lsome/annotation;
|
||||
value1 = "test"
|
||||
value2 = .subannotation Lsome/annotation;
|
||||
value1 = "test2"
|
||||
value2 = Lsome/enum;
|
||||
.end subannotation
|
||||
.end subannotation
|
||||
|
||||
.field public static staticFieldWithAnnotation:I
|
||||
.annotation runtime La/field/annotation;
|
||||
this = "is"
|
||||
a = "test"
|
||||
.end annotation
|
||||
.annotation runtime Lorg/junit/Test;
|
||||
.end annotation
|
||||
.end field
|
||||
|
||||
.field public instanceField:Ljava/lang/String;
|
||||
|
||||
|
||||
|
||||
.method public constructor <init>()V
|
||||
.registers 1
|
||||
invoke-direct {p0}, Ljava/lang/Object;-><init>()V
|
||||
return-void
|
||||
.end method
|
||||
|
||||
.method public testMethod(ILjava/lang/String;)Ljava/lang/String;
|
||||
.registers 3
|
||||
.annotation runtime Lorg/junit/Test;
|
||||
.end annotation
|
||||
.annotation system Lyet/another/annotation;
|
||||
somevalue = 1234
|
||||
anothervalue = 3.14159
|
||||
.end annotation
|
||||
|
||||
const-string v0, "testing\n123"
|
||||
|
||||
goto switch:
|
||||
|
||||
sget v0, Lbaksmali/test/class;->staticField:I
|
||||
|
||||
switch:
|
||||
packed-switch v0, pswitch:
|
||||
|
||||
try_start:
|
||||
const/4 v0, 7
|
||||
const v0, 10
|
||||
nop
|
||||
try_end:
|
||||
.catch Ljava/lang/Exception; {try_start: .. try_end:} handler:
|
||||
.catchall {try_start: .. try_end:} handler2:
|
||||
|
||||
handler:
|
||||
|
||||
Label10:
|
||||
Label11:
|
||||
Label12:
|
||||
Label13:
|
||||
return-object v0
|
||||
|
||||
|
||||
|
||||
.array-data 4
|
||||
1 2 3 4 5 6 200
|
||||
.end array-data
|
||||
|
||||
pswitch:
|
||||
.packed-switch 10
|
||||
Label10:
|
||||
Label11:
|
||||
Label12:
|
||||
Label13:
|
||||
.end packed-switch
|
||||
|
||||
handler2:
|
||||
|
||||
return-void
|
||||
|
||||
.end method
|
||||
|
||||
.method public abstract testMethod2()V
|
||||
.annotation runtime Lsome/annotation;
|
||||
subannotation = .subannotation Lsome/other/annotation;
|
||||
value = "value"
|
||||
.end subannotation
|
||||
.end annotation
|
||||
.annotation runtime Lorg/junit/Test;
|
||||
.end annotation
|
||||
.end method
|
||||
|
||||
|
||||
.method public tryTest()V
|
||||
.registers 1
|
||||
|
||||
handler:
|
||||
nop
|
||||
|
||||
|
||||
try_start:
|
||||
const/4 v0, 7
|
||||
const v0, 10
|
||||
nop
|
||||
try_end:
|
||||
.catch Ljava/lang/Exception; {try_start: .. try_end:} handler:
|
||||
.end method
|
||||
|
||||
|
||||
.method public debugTest(IIIII)V
|
||||
.registers 10
|
||||
|
||||
.parameter "Blah"
|
||||
.parameter
|
||||
.parameter "BlahWithAnnotations"
|
||||
.annotation runtime Lsome/annotation;
|
||||
something = "some value"
|
||||
somethingelse = 1234
|
||||
.end annotation
|
||||
.annotation runtime La/second/annotation;
|
||||
.end annotation
|
||||
.end parameter
|
||||
.parameter
|
||||
.annotation runtime Lsome/annotation;
|
||||
something = "some value"
|
||||
somethingelse = 1234
|
||||
.end annotation
|
||||
.end parameter
|
||||
.parameter "LastParam"
|
||||
|
||||
.prologue
|
||||
|
||||
nop
|
||||
nop
|
||||
|
||||
.source "somefile.java"
|
||||
.line 101
|
||||
|
||||
nop
|
||||
|
||||
|
||||
.line 50
|
||||
|
||||
.local v0, aNumber:I
|
||||
const v0, 1234
|
||||
.end local v0
|
||||
|
||||
.source "someotherfile.java"
|
||||
.line 900
|
||||
|
||||
const-string v0, "1234"
|
||||
|
||||
.restart local v0
|
||||
const v0, 6789
|
||||
.end local v0
|
||||
|
||||
.epilogue
|
||||
|
||||
.end method
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user