mirror of
https://github.com/revanced/Apktool.git
synced 2025-05-21 15:17:05 +02:00
Added new mechanisms of smali decoding and building.
This commit is contained in:
parent
f9c9588f1d
commit
060572e824
225
src/brut/androlib/src/DebugInjector.java
Normal file
225
src/brut/androlib/src/DebugInjector.java
Normal file
@ -0,0 +1,225 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010 Ryszard Wiśniewski <brut.alll@gmail.com>.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package brut.androlib.src;
|
||||||
|
|
||||||
|
import brut.androlib.AndrolibException;
|
||||||
|
import java.util.ListIterator;
|
||||||
|
import org.jf.dexlib.Code.Opcode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Ryszard Wiśniewski <brut.alll@gmail.com>
|
||||||
|
*/
|
||||||
|
public class DebugInjector {
|
||||||
|
|
||||||
|
public static void inject(ListIterator<String> it, StringBuilder out)
|
||||||
|
throws AndrolibException {
|
||||||
|
new DebugInjector(it, out).inject();
|
||||||
|
}
|
||||||
|
|
||||||
|
private DebugInjector(ListIterator<String> it, StringBuilder out) {
|
||||||
|
mIt = it;
|
||||||
|
mOut = out;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void inject() throws AndrolibException {
|
||||||
|
String definition = nextAndAppend();
|
||||||
|
if (definition.contains(" abstract ")) {
|
||||||
|
nextAndAppend();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
injectParameters(definition);
|
||||||
|
|
||||||
|
boolean end = false;
|
||||||
|
while (!end) {
|
||||||
|
end = step();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void injectParameters(String definition) throws AndrolibException {
|
||||||
|
int pos = definition.indexOf('(');
|
||||||
|
if (pos == -1) {
|
||||||
|
throw new AndrolibException();
|
||||||
|
}
|
||||||
|
int pos2 = definition.indexOf(')', pos);
|
||||||
|
if (pos2 == -1) {
|
||||||
|
throw new AndrolibException();
|
||||||
|
}
|
||||||
|
String params = definition.substring(pos + 1, pos2);
|
||||||
|
|
||||||
|
int i = definition.contains(" static ") ? 0 : 1;
|
||||||
|
int argc = TypeName.listFromInternalName(params).size() + i;
|
||||||
|
while(i < argc) {
|
||||||
|
mOut.append(".parameter \"p").append(i).append("\"\n");
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean step() {
|
||||||
|
String line = next();
|
||||||
|
if (line.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (line.charAt(0)) {
|
||||||
|
case '#':
|
||||||
|
return false;
|
||||||
|
case ':':
|
||||||
|
append(line);
|
||||||
|
return false;
|
||||||
|
case '.':
|
||||||
|
return processDirective(line);
|
||||||
|
default:
|
||||||
|
return processInstruction(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean processDirective(String line) {
|
||||||
|
String line2 = line.substring(1);
|
||||||
|
if (
|
||||||
|
line2.startsWith("line ") ||
|
||||||
|
line2.equals("prologue") ||
|
||||||
|
line2.startsWith("local ") ||
|
||||||
|
line2.startsWith("parameter")
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
append(line);
|
||||||
|
if (line2.equals("end method")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
line2.startsWith("annotation ") ||
|
||||||
|
line2.equals("sparse-switch") ||
|
||||||
|
line2.startsWith("packed-switch ") ||
|
||||||
|
line2.startsWith("array-data ")
|
||||||
|
) {
|
||||||
|
while(true) {
|
||||||
|
line2 = nextAndAppend();
|
||||||
|
if (line2.startsWith(".end ")) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean processInstruction(String line) {
|
||||||
|
if (mFirstInstruction) {
|
||||||
|
mOut.append(".prologue\n");
|
||||||
|
mFirstInstruction = false;
|
||||||
|
}
|
||||||
|
mOut.append(".line ").append(mIt.nextIndex()).append('\n')
|
||||||
|
.append(line).append('\n');
|
||||||
|
|
||||||
|
int pos = line.indexOf(' ');
|
||||||
|
if (pos == -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Opcode opcode = Opcode.getOpcodeByName(line.substring(0, pos));
|
||||||
|
if (! opcode.setsRegister()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pos2 = line.indexOf(',', pos);
|
||||||
|
String register = pos2 == -1 ? line.substring(pos + 1) :
|
||||||
|
line.substring(pos + 1, pos2);
|
||||||
|
|
||||||
|
mOut.append(".local ").append(register).append(", ").append(register)
|
||||||
|
.append(':').append(getRegisterTypeForOpcode(opcode)).append('\n');
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getRegisterTypeForOpcode(Opcode opcode) {
|
||||||
|
switch (opcode.value) {
|
||||||
|
case (byte)0x0d: // ?
|
||||||
|
case (byte)0x1a:
|
||||||
|
case (byte)0x1b:
|
||||||
|
case (byte)0x1c: // ?
|
||||||
|
case (byte)0x22:
|
||||||
|
case (byte)0x23: // ?
|
||||||
|
case (byte)0xf4: // ?
|
||||||
|
return "Ljava/lang/Object;";
|
||||||
|
case (byte)0x1f: // ?
|
||||||
|
case (byte)0x20: // ?
|
||||||
|
return "Z";
|
||||||
|
case (byte)0x21: // ?
|
||||||
|
return "I";
|
||||||
|
}
|
||||||
|
|
||||||
|
String name = opcode.name;
|
||||||
|
int pos = name.lastIndexOf('-');
|
||||||
|
if (pos != -1) {
|
||||||
|
int pos2 = name.indexOf('/');
|
||||||
|
String type = pos2 == -1 ? name.substring(pos + 1) :
|
||||||
|
name.substring(pos + 1, pos2);
|
||||||
|
|
||||||
|
if (type.equals("object")) {
|
||||||
|
return "Ljava/lang/Object;";
|
||||||
|
}
|
||||||
|
if (type.equals("int")) {
|
||||||
|
return "I";
|
||||||
|
}
|
||||||
|
if (type.equals("boolean")) {
|
||||||
|
return "Z";
|
||||||
|
}
|
||||||
|
if (type.equals("float")) {
|
||||||
|
return "F";
|
||||||
|
}
|
||||||
|
if (type.equals("double")) {
|
||||||
|
return "D";
|
||||||
|
}
|
||||||
|
if (type.equals("long")) {
|
||||||
|
return "J";
|
||||||
|
}
|
||||||
|
if (type.equals("byte")) {
|
||||||
|
return "B";
|
||||||
|
}
|
||||||
|
if (type.equals("char")) {
|
||||||
|
return "C";
|
||||||
|
}
|
||||||
|
if (type.equals("short")) {
|
||||||
|
return "S";
|
||||||
|
}
|
||||||
|
if (type.equals("long")) {
|
||||||
|
return "J";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "I";
|
||||||
|
}
|
||||||
|
|
||||||
|
private String next() {
|
||||||
|
return mIt.next().trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String nextAndAppend() {
|
||||||
|
String line = next();
|
||||||
|
append(line);
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void append(String append) {
|
||||||
|
mOut.append(append).append('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
private final ListIterator<String> mIt;
|
||||||
|
private final StringBuilder mOut;
|
||||||
|
|
||||||
|
private boolean mFirstInstruction = true;
|
||||||
|
}
|
109
src/brut/androlib/src/SmaliBuilder.java
Normal file
109
src/brut/androlib/src/SmaliBuilder.java
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010 Ryszard Wiśniewski <brut.alll@gmail.com>.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package brut.androlib.src;
|
||||||
|
|
||||||
|
import brut.androlib.AndrolibException;
|
||||||
|
import brut.androlib.res.util.ExtFile;
|
||||||
|
import brut.androlib.util.DexFileBuilder;
|
||||||
|
import brut.directory.DirectoryException;
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ListIterator;
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Ryszard Wiśniewski <brut.alll@gmail.com>
|
||||||
|
*/
|
||||||
|
public class SmaliBuilder {
|
||||||
|
|
||||||
|
public static void build(ExtFile smaliDir, File dexFile, boolean debug)
|
||||||
|
throws AndrolibException {
|
||||||
|
new SmaliBuilder(smaliDir, dexFile, debug).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private SmaliBuilder(ExtFile smaliDir, File dexFile, boolean debug) {
|
||||||
|
mSmaliDir = smaliDir;
|
||||||
|
mDexFile = dexFile;
|
||||||
|
mDebug = debug;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void build() throws AndrolibException {
|
||||||
|
try {
|
||||||
|
mDexBuilder = new DexFileBuilder();
|
||||||
|
for (String fileName : mSmaliDir.getDirectory().getFiles(true)) {
|
||||||
|
buildFile(fileName);
|
||||||
|
}
|
||||||
|
mDexBuilder.writeTo(mDexFile);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
throw new AndrolibException(ex);
|
||||||
|
} catch (DirectoryException ex) {
|
||||||
|
throw new AndrolibException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void buildFile(String fileName) throws AndrolibException,
|
||||||
|
IOException {
|
||||||
|
File inFile = new File(mSmaliDir, fileName);
|
||||||
|
InputStream inStream = new FileInputStream(inFile);
|
||||||
|
|
||||||
|
if (fileName.endsWith(".smali")) {
|
||||||
|
mDexBuilder.addSmaliFile(inFile);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (! fileName.endsWith(".java")) {
|
||||||
|
throw new AndrolibException("Unknown file type: " + inFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder out = new StringBuilder();
|
||||||
|
List<String> lines = IOUtils.readLines(inStream);
|
||||||
|
|
||||||
|
if (!mDebug) {
|
||||||
|
final String[] linesArray = lines.toArray(new String[0]);
|
||||||
|
for (int i = 2; i < linesArray.length - 2; i++) {
|
||||||
|
out.append(linesArray[i]).append('\n');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
lines.remove(lines.size() - 1);
|
||||||
|
lines.remove(lines.size() - 1);
|
||||||
|
ListIterator<String> it = lines.listIterator(2);
|
||||||
|
|
||||||
|
out.append(".source \"").append(inFile.getName()).append("\"\n");
|
||||||
|
while (it.hasNext()) {
|
||||||
|
String line = it.next().trim();
|
||||||
|
if (line.isEmpty() || line.charAt(0) == '#' ||
|
||||||
|
line.startsWith(".source")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (line.startsWith(".method ")) {
|
||||||
|
it.previous();
|
||||||
|
DebugInjector.inject(it, out);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
out.append(line).append('\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mDexBuilder.addSmaliFile(
|
||||||
|
IOUtils.toInputStream(out.toString()), fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final ExtFile mSmaliDir;
|
||||||
|
private final File mDexFile;
|
||||||
|
private final boolean mDebug;
|
||||||
|
|
||||||
|
private DexFileBuilder mDexBuilder;
|
||||||
|
}
|
88
src/brut/androlib/src/SmaliDecoder.java
Normal file
88
src/brut/androlib/src/SmaliDecoder.java
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010 Ryszard Wiśniewski <brut.alll@gmail.com>.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package brut.androlib.src;
|
||||||
|
|
||||||
|
import brut.androlib.AndrolibException;
|
||||||
|
import brut.androlib.src.mod.IndentingWriter;
|
||||||
|
import java.io.*;
|
||||||
|
import org.jf.baksmali.Adaptors.ClassDefinition;
|
||||||
|
import org.jf.baksmali.baksmali;
|
||||||
|
import org.jf.dexlib.ClassDefItem;
|
||||||
|
import org.jf.dexlib.DexFile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Ryszard Wiśniewski <brut.alll@gmail.com>
|
||||||
|
*/
|
||||||
|
public class SmaliDecoder {
|
||||||
|
|
||||||
|
public static void decode(File apkFile, File outDir, boolean debug)
|
||||||
|
throws AndrolibException {
|
||||||
|
new SmaliDecoder(apkFile, outDir, debug).decode();
|
||||||
|
}
|
||||||
|
|
||||||
|
private SmaliDecoder(File apkFile, File outDir, boolean debug) {
|
||||||
|
mApkFile = apkFile;
|
||||||
|
mOutDir = outDir;
|
||||||
|
mDebug = debug;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void decode() throws AndrolibException {
|
||||||
|
try {
|
||||||
|
baksmali.useLocalsDirective = true;
|
||||||
|
baksmali.useSequentialLabels = true;
|
||||||
|
|
||||||
|
DexFile dexFile = new DexFile(mApkFile);
|
||||||
|
for (ClassDefItem classDefItem :
|
||||||
|
dexFile.ClassDefsSection.getItems()) {
|
||||||
|
decodeClassDefItem(classDefItem);
|
||||||
|
}
|
||||||
|
} catch (IOException ex) {
|
||||||
|
throw new AndrolibException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void decodeClassDefItem(ClassDefItem classDefItem)
|
||||||
|
throws AndrolibException, IOException {
|
||||||
|
TypeName name = TypeName.fromInternalName(
|
||||||
|
classDefItem.getClassType().getTypeDescriptor());
|
||||||
|
File outFile = new File(mOutDir, name.getFilePath(true)
|
||||||
|
+ (mDebug ? ".java" : ".smali"));
|
||||||
|
|
||||||
|
if (outFile.exists()) {
|
||||||
|
throw new AndrolibException(
|
||||||
|
"File already exists: " + outFile);
|
||||||
|
}
|
||||||
|
outFile.getParentFile().mkdirs();
|
||||||
|
|
||||||
|
IndentingWriter indentWriter =
|
||||||
|
new IndentingWriter(new FileWriter(outFile));
|
||||||
|
|
||||||
|
if (mDebug) {
|
||||||
|
indentWriter.write("package " + name.package_ + "; class "
|
||||||
|
+ name.getName(true, true) + " {/*\n\n");
|
||||||
|
}
|
||||||
|
new ClassDefinition(classDefItem).writeTo(indentWriter);
|
||||||
|
if (mDebug) {
|
||||||
|
indentWriter.write("\n*/}\n");
|
||||||
|
}
|
||||||
|
indentWriter.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private final File mApkFile;
|
||||||
|
private final File mOutDir;
|
||||||
|
private final boolean mDebug;
|
||||||
|
}
|
205
src/brut/androlib/src/TypeName.java
Normal file
205
src/brut/androlib/src/TypeName.java
Normal file
@ -0,0 +1,205 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010 Ryszard Wiśniewski <brut.alll@gmail.com>.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package brut.androlib.src;
|
||||||
|
|
||||||
|
import brut.androlib.AndrolibException;
|
||||||
|
import brut.util.Duo;
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Ryszard Wiśniewski <brut.alll@gmail.com>
|
||||||
|
*/
|
||||||
|
public class TypeName {
|
||||||
|
public final String package_;
|
||||||
|
public final String type;
|
||||||
|
public final String innerType;
|
||||||
|
public final int array;
|
||||||
|
|
||||||
|
public TypeName(String type, int array) {
|
||||||
|
this(null, type, null, array);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TypeName(String package_, String type, String innerType, int array) {
|
||||||
|
this.package_ = package_;
|
||||||
|
this.type = type;
|
||||||
|
this.innerType = innerType;
|
||||||
|
this.array = array;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getShortenedName() {
|
||||||
|
return getName("java.lang".equals(package_), isFileOwner());
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return getName(false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName(boolean excludePackage, boolean separateInner) {
|
||||||
|
String name =
|
||||||
|
(package_ == null || excludePackage ? "" : package_ + '.') +
|
||||||
|
type +
|
||||||
|
(innerType != null ? (separateInner ? '$' : '.') + innerType : "");
|
||||||
|
for (int i = 0; i < array; i++) {
|
||||||
|
name += "[]";
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getJavaFilePath() {
|
||||||
|
return getFilePath(isFileOwner()) + ".java";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSmaliFilePath() {
|
||||||
|
return getFilePath(true) + ".smali";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFilePath(boolean separateInner) {
|
||||||
|
return package_.replace('.', File.separatorChar) + File.separatorChar
|
||||||
|
+ type + (separateInner && isInner() ? "$" + innerType : "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isInner() {
|
||||||
|
return innerType != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isArray() {
|
||||||
|
return array != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isFileOwner() {
|
||||||
|
if (mIsFileOwner == null) {
|
||||||
|
mIsFileOwner = true;
|
||||||
|
if (isInner()) {
|
||||||
|
char c = innerType.charAt(0);
|
||||||
|
if (c < '0' || c > '9') {
|
||||||
|
mIsFileOwner = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mIsFileOwner;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TypeName fromInternalName(String internal)
|
||||||
|
throws AndrolibException {
|
||||||
|
Duo<TypeName, Integer> duo = fetchFromInternalName(internal);
|
||||||
|
if (duo.m2 != internal.length()) {
|
||||||
|
throw new AndrolibException(
|
||||||
|
"Invalid internal name: " + internal);
|
||||||
|
}
|
||||||
|
return duo.m1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<TypeName> listFromInternalName(String internal)
|
||||||
|
throws AndrolibException {
|
||||||
|
List<TypeName> types = new ArrayList<TypeName>();
|
||||||
|
while (! internal.isEmpty()) {
|
||||||
|
Duo<TypeName, Integer> duo = fetchFromInternalName(internal);
|
||||||
|
types.add(duo.m1);
|
||||||
|
internal = internal.substring(duo.m2);
|
||||||
|
}
|
||||||
|
return types;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Duo<TypeName, Integer> fetchFromInternalName(String internal)
|
||||||
|
throws AndrolibException {
|
||||||
|
String origInternal = internal;
|
||||||
|
int array = 0;
|
||||||
|
|
||||||
|
boolean isArray = false;
|
||||||
|
do {
|
||||||
|
if (internal.isEmpty()) {
|
||||||
|
throw new AndrolibException(
|
||||||
|
"Invalid internal name: " + origInternal);
|
||||||
|
}
|
||||||
|
isArray = internal.charAt(0) == '[';
|
||||||
|
if (isArray) {
|
||||||
|
array++;
|
||||||
|
internal = internal.substring(1);
|
||||||
|
}
|
||||||
|
} while (isArray);
|
||||||
|
|
||||||
|
int length = array + 1;
|
||||||
|
String package_ = null;
|
||||||
|
String type = null;
|
||||||
|
String innerType = null;
|
||||||
|
switch (internal.charAt(0)) {
|
||||||
|
case 'B':
|
||||||
|
type = "byte";
|
||||||
|
break;
|
||||||
|
case 'C':
|
||||||
|
type = "char";
|
||||||
|
break;
|
||||||
|
case 'D':
|
||||||
|
type = "double";
|
||||||
|
break;
|
||||||
|
case 'F':
|
||||||
|
type = "float";
|
||||||
|
break;
|
||||||
|
case 'I':
|
||||||
|
type = "int";
|
||||||
|
break;
|
||||||
|
case 'J':
|
||||||
|
type = "long";
|
||||||
|
break;
|
||||||
|
case 'S':
|
||||||
|
type = "short";
|
||||||
|
break;
|
||||||
|
case 'Z':
|
||||||
|
type = "boolean";
|
||||||
|
break;
|
||||||
|
case 'V':
|
||||||
|
type = "void";
|
||||||
|
break;
|
||||||
|
case 'L':
|
||||||
|
int pos = internal.indexOf(';');
|
||||||
|
if (pos == -1) {
|
||||||
|
throw new AndrolibException(
|
||||||
|
"Invalid internal name: " + origInternal);
|
||||||
|
}
|
||||||
|
length += pos;
|
||||||
|
internal = internal.substring(1, pos);
|
||||||
|
|
||||||
|
pos = internal.lastIndexOf('/');
|
||||||
|
package_ = internal.substring(0, pos).replace('/', '.');
|
||||||
|
type = internal.substring(pos + 1);
|
||||||
|
|
||||||
|
pos = type.indexOf('$');
|
||||||
|
if (pos != -1) {
|
||||||
|
innerType = type.substring(pos + 1);
|
||||||
|
type = type.substring(0, pos);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new AndrolibException(
|
||||||
|
"Invalid internal name: " + origInternal);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Duo<TypeName, Integer>(
|
||||||
|
new TypeName(package_, type, innerType, array), length);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Boolean mIsFileOwner;
|
||||||
|
}
|
29
src/brut/androlib/src/mod/IndentingWriter.java
Normal file
29
src/brut/androlib/src/mod/IndentingWriter.java
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010 Ryszard Wiśniewski <brut.alll@gmail.com>.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package brut.androlib.src.mod;
|
||||||
|
|
||||||
|
import java.io.Writer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Ryszard Wiśniewski <brut.alll@gmail.com>
|
||||||
|
*/
|
||||||
|
public class IndentingWriter extends org.jf.baksmali.IndentingWriter {
|
||||||
|
|
||||||
|
public IndentingWriter(Writer writer) {
|
||||||
|
super(writer);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user