mirror of
https://github.com/revanced/smali.git
synced 2025-05-03 16:14:29 +02:00
Add support for an --api-level parameter
This commit is contained in:
parent
6729493700
commit
c2f08d5123
@ -29,6 +29,7 @@
|
|||||||
package org.jf.baksmali;
|
package org.jf.baksmali;
|
||||||
|
|
||||||
import org.apache.commons.cli.*;
|
import org.apache.commons.cli.*;
|
||||||
|
import org.jf.dexlib.Code.Opcode;
|
||||||
import org.jf.dexlib.DexFile;
|
import org.jf.dexlib.DexFile;
|
||||||
import org.jf.util.ConsoleUtil;
|
import org.jf.util.ConsoleUtil;
|
||||||
import org.jf.util.smaliHelpFormatter;
|
import org.jf.util.smaliHelpFormatter;
|
||||||
@ -108,6 +109,8 @@ public class main {
|
|||||||
boolean verify = false;
|
boolean verify = false;
|
||||||
boolean ignoreErrors = false;
|
boolean ignoreErrors = false;
|
||||||
|
|
||||||
|
int apiLevel = 14;
|
||||||
|
|
||||||
int registerInfo = 0;
|
int registerInfo = 0;
|
||||||
|
|
||||||
String outputDirectory = "out";
|
String outputDirectory = "out";
|
||||||
@ -208,6 +211,9 @@ public class main {
|
|||||||
case 'm':
|
case 'm':
|
||||||
noAccessorComments = true;
|
noAccessorComments = true;
|
||||||
break;
|
break;
|
||||||
|
case 'a':
|
||||||
|
apiLevel = Integer.parseInt(commandLine.getOptionValue("a"));
|
||||||
|
break;
|
||||||
case 'N':
|
case 'N':
|
||||||
disassemble = false;
|
disassemble = false;
|
||||||
break;
|
break;
|
||||||
@ -279,6 +285,8 @@ public class main {
|
|||||||
bootClassPathDirsArray[i] = bootClassPathDirs.get(i);
|
bootClassPathDirsArray[i] = bootClassPathDirs.get(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Opcode.updateMapsForApiLevel(apiLevel);
|
||||||
|
|
||||||
baksmali.disassembleDexFile(dexFileFile.getPath(), dexFile, deodex, outputDirectory,
|
baksmali.disassembleDexFile(dexFileFile.getPath(), dexFile, deodex, outputDirectory,
|
||||||
bootClassPathDirsArray, bootClassPath, extraBootClassPathEntries.toString(),
|
bootClassPathDirsArray, bootClassPath, extraBootClassPathEntries.toString(),
|
||||||
noParameterRegisters, useLocalsDirective, useSequentialLabels, outputDebugInfo, addCodeOffsets,
|
noParameterRegisters, useLocalsDirective, useSequentialLabels, outputDebugInfo, addCodeOffsets,
|
||||||
@ -415,6 +423,13 @@ public class main {
|
|||||||
.withDescription("don't output helper comments for synthetic accessors")
|
.withDescription("don't output helper comments for synthetic accessors")
|
||||||
.create("m");
|
.create("m");
|
||||||
|
|
||||||
|
Option apiLevelOption = OptionBuilder.withLongOpt("api-level")
|
||||||
|
.withDescription("The numeric api-level of the file being disassembled. If not " +
|
||||||
|
"specified, it defaults to 14 (ICS).")
|
||||||
|
.hasArg()
|
||||||
|
.withArgName("API_LEVEL")
|
||||||
|
.create("a");
|
||||||
|
|
||||||
Option dumpOption = OptionBuilder.withLongOpt("dump-to")
|
Option dumpOption = OptionBuilder.withLongOpt("dump-to")
|
||||||
.withDescription("dumps the given dex file into a single annotated dump file named FILE" +
|
.withDescription("dumps the given dex file into a single annotated dump file named FILE" +
|
||||||
" (<dexfile>.dump by default), along with the normal disassembly")
|
" (<dexfile>.dump by default), along with the normal disassembly")
|
||||||
@ -464,6 +479,7 @@ public class main {
|
|||||||
basicOptions.addOption(classPathDirOption);
|
basicOptions.addOption(classPathDirOption);
|
||||||
basicOptions.addOption(codeOffsetOption);
|
basicOptions.addOption(codeOffsetOption);
|
||||||
basicOptions.addOption(noAccessorCommentsOption);
|
basicOptions.addOption(noAccessorCommentsOption);
|
||||||
|
basicOptions.addOption(apiLevelOption);
|
||||||
|
|
||||||
debugOptions.addOption(dumpOption);
|
debugOptions.addOption(dumpOption);
|
||||||
debugOptions.addOption(ignoreErrorsOption);
|
debugOptions.addOption(ignoreErrorsOption);
|
||||||
|
@ -73,7 +73,12 @@ public class Instruction21c extends InstructionWithReference implements SingleRe
|
|||||||
|
|
||||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||||
if(getReferencedItem().getIndex() > 0xFFFF) {
|
if(getReferencedItem().getIndex() > 0xFFFF) {
|
||||||
throw new RuntimeException(String.format("%s index is too large. Use the %s/jumbo instruction instead.", opcode.referenceType.name(), opcode.name));
|
if (opcode.hasJumboOpcode()) {
|
||||||
|
throw new RuntimeException(String.format("%s index is too large. Use the %s instruction instead.",
|
||||||
|
opcode.referenceType.name(), opcode.getJumboOpcode().name));
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException(String.format("%s index is too large", opcode.referenceType.name()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out.writeByte(opcode.value);
|
out.writeByte(opcode.value);
|
||||||
|
@ -64,7 +64,12 @@ public class Instruction22c extends InstructionWithReference implements TwoRegis
|
|||||||
|
|
||||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||||
if(getReferencedItem().getIndex() > 0xFFFF) {
|
if(getReferencedItem().getIndex() > 0xFFFF) {
|
||||||
throw new RuntimeException(String.format("%s index is too large. Use the %s/jumbo instruction instead.", opcode.referenceType.name(), opcode.name));
|
if (opcode.hasJumboOpcode()) {
|
||||||
|
throw new RuntimeException(String.format("%s index is too large. Use the %s instruction instead.",
|
||||||
|
opcode.referenceType.name(), opcode.getJumboOpcode().name));
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException(String.format("%s index is too large.", opcode.referenceType.name()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out.writeByte(opcode.value);
|
out.writeByte(opcode.value);
|
||||||
|
@ -95,7 +95,12 @@ public class Instruction35c extends InstructionWithReference implements FiveRegi
|
|||||||
|
|
||||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||||
if(getReferencedItem().getIndex() > 0xFFFF) {
|
if(getReferencedItem().getIndex() > 0xFFFF) {
|
||||||
throw new RuntimeException(String.format("%s index is too large. Use the %s/jumbo instruction instead.", opcode.referenceType.name(), opcode.name));
|
if (opcode.hasJumboOpcode()) {
|
||||||
|
throw new RuntimeException(String.format("%s index is too large. Use the %s instruction instead.",
|
||||||
|
opcode.referenceType.name(), opcode.getJumboOpcode().name));
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException(String.format("%s index is too large.", opcode.referenceType.name()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out.writeByte(opcode.value);
|
out.writeByte(opcode.value);
|
||||||
|
@ -81,7 +81,12 @@ public class Instruction3rc extends InstructionWithReference implements Register
|
|||||||
|
|
||||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||||
if(getReferencedItem().getIndex() > 0xFFFF) {
|
if(getReferencedItem().getIndex() > 0xFFFF) {
|
||||||
throw new RuntimeException(String.format("%s index is too large. Use the jumbo variant of the instruction instead.", opcode.referenceType.name()));
|
if (opcode.hasJumboOpcode()) {
|
||||||
|
throw new RuntimeException(String.format("%s index is too large. Use the %s instruction instead.",
|
||||||
|
opcode.referenceType.name(), opcode.getJumboOpcode().name));
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException(String.format("%s index is too large.", opcode.referenceType.name()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out.writeByte(opcode.value);
|
out.writeByte(opcode.value);
|
||||||
|
@ -374,6 +374,47 @@ public enum Opcode
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void removeOpcodes(Opcode... toRemove) {
|
||||||
|
for (Opcode opcode: toRemove) {
|
||||||
|
opcodesByName.remove(opcode.name.toLowerCase().hashCode());
|
||||||
|
|
||||||
|
if (((opcode.value >> 8) & 0xFF) == 0x00) {
|
||||||
|
opcodesByValue[opcode.value] = null;
|
||||||
|
} else {
|
||||||
|
expandedOpcodesByValue[opcode.value & 0xFF] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This will add/remove/replace various opcodes in the value/name maps as needed,
|
||||||
|
* based on the idiosyncrasies of that api level
|
||||||
|
* @param apiLevel
|
||||||
|
*/
|
||||||
|
public static void updateMapsForApiLevel(int apiLevel) {
|
||||||
|
if (apiLevel < 5) {
|
||||||
|
removeOpcodes(THROW_VERIFICATION_ERROR);
|
||||||
|
}
|
||||||
|
if (apiLevel < 8) {
|
||||||
|
removeOpcodes(EXECUTE_INLINE_RANGE);
|
||||||
|
}
|
||||||
|
if (apiLevel < 9) {
|
||||||
|
removeOpcodes(IGET_VOLATILE, IPUT_VOLATILE, SGET_VOLATILE, SPUT_VOLATILE, IGET_OBJECT_VOLATILE,
|
||||||
|
IGET_WIDE_VOLATILE, IPUT_WIDE_VOLATILE, SGET_WIDE_VOLATILE, SPUT_WIDE_VOLATILE,
|
||||||
|
IPUT_OBJECT_VOLATILE, SGET_OBJECT_VOLATILE, SPUT_OBJECT_VOLATILE);
|
||||||
|
}
|
||||||
|
if (apiLevel < 14) {
|
||||||
|
removeOpcodes(CONST_CLASS_JUMBO, CHECK_CAST_JUMBO, INSTANCE_OF_JUMBO, NEW_INSTANCE_JUMBO,
|
||||||
|
NEW_ARRAY_JUMBO, FILLED_NEW_ARRAY_JUMBO, IGET_JUMBO, IGET_WIDE_JUMBO, IGET_OBJECT_JUMBO,
|
||||||
|
IGET_BOOLEAN_JUMBO, IGET_BYTE_JUMBO, IGET_CHAR_JUMBO, IGET_SHORT_JUMBO, IPUT_JUMBO, IPUT_WIDE_JUMBO,
|
||||||
|
IPUT_OBJECT_JUMBO, IPUT_BOOLEAN_JUMBO, IPUT_BYTE_JUMBO, IPUT_CHAR_JUMBO, IPUT_SHORT_JUMBO,
|
||||||
|
SGET_JUMBO, SGET_WIDE_JUMBO, SGET_OBJECT_JUMBO, SGET_BOOLEAN_JUMBO, SGET_BYTE_JUMBO,
|
||||||
|
SGET_CHAR_JUMBO, SGET_SHORT_JUMBO, SPUT_JUMBO, SPUT_WIDE_JUMBO, SPUT_OBJECT_JUMBO,
|
||||||
|
SPUT_BOOLEAN_JUMBO, SPUT_BYTE_JUMBO, SPUT_CHAR_JUMBO, SPUT_SHORT_JUMBO, INVOKE_VIRTUAL_JUMBO,
|
||||||
|
INVOKE_SUPER_JUMBO, INVOKE_DIRECT_JUMBO, INVOKE_STATIC_JUMBO, INVOKE_INTERFACE_JUMBO);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public final short value;
|
public final short value;
|
||||||
public final String name;
|
public final String name;
|
||||||
public final ReferenceType referenceType;
|
public final ReferenceType referenceType;
|
||||||
@ -435,7 +476,7 @@ public enum Opcode
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final boolean hasJumboOpcode() {
|
public final boolean hasJumboOpcode() {
|
||||||
return jumboOpcode != -1;
|
return jumboOpcode != -1 && Opcode.getOpcodeByValue(jumboOpcode) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final Opcode getJumboOpcode() {
|
public final Opcode getJumboOpcode() {
|
||||||
|
@ -458,12 +458,15 @@ public class CodeItem extends Item<CodeItem> {
|
|||||||
InstructionWithJumboVariant instructionWithJumboVariant =
|
InstructionWithJumboVariant instructionWithJumboVariant =
|
||||||
(InstructionWithJumboVariant)referenceInstruction;
|
(InstructionWithJumboVariant)referenceInstruction;
|
||||||
|
|
||||||
|
Instruction jumboInstruction = instructionWithJumboVariant.makeJumbo();
|
||||||
|
if (jumboInstruction != null) {
|
||||||
replaceInstructionAtAddress(currentCodeAddress,
|
replaceInstructionAtAddress(currentCodeAddress,
|
||||||
instructionWithJumboVariant.makeJumbo());
|
instructionWithJumboVariant.makeJumbo());
|
||||||
didSomething = true;
|
didSomething = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
currentCodeAddress += instruction.getSize(currentCodeAddress);
|
currentCodeAddress += instruction.getSize(currentCodeAddress);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
|
@ -32,6 +32,7 @@ import org.antlr.runtime.*;
|
|||||||
import org.antlr.runtime.tree.CommonTree;
|
import org.antlr.runtime.tree.CommonTree;
|
||||||
import org.antlr.runtime.tree.CommonTreeNodeStream;
|
import org.antlr.runtime.tree.CommonTreeNodeStream;
|
||||||
import org.apache.commons.cli.*;
|
import org.apache.commons.cli.*;
|
||||||
|
import org.jf.dexlib.Code.Opcode;
|
||||||
import org.jf.dexlib.CodeItem;
|
import org.jf.dexlib.CodeItem;
|
||||||
import org.jf.dexlib.DexFile;
|
import org.jf.dexlib.DexFile;
|
||||||
import org.jf.dexlib.Util.ByteArrayAnnotatedOutput;
|
import org.jf.dexlib.Util.ByteArrayAnnotatedOutput;
|
||||||
@ -106,6 +107,8 @@ public class main {
|
|||||||
boolean oldLexer = false;
|
boolean oldLexer = false;
|
||||||
boolean printTokens = false;
|
boolean printTokens = false;
|
||||||
|
|
||||||
|
int apiLevel = 14;
|
||||||
|
|
||||||
String outputDexFile = "out.dex";
|
String outputDexFile = "out.dex";
|
||||||
String dumpFileName = null;
|
String dumpFileName = null;
|
||||||
|
|
||||||
@ -136,6 +139,9 @@ public class main {
|
|||||||
case 'x':
|
case 'x':
|
||||||
allowOdex = true;
|
allowOdex = true;
|
||||||
break;
|
break;
|
||||||
|
case 'a':
|
||||||
|
apiLevel = Integer.parseInt(commandLine.getOptionValue("a"));
|
||||||
|
break;
|
||||||
case 'D':
|
case 'D':
|
||||||
dumpFileName = commandLine.getOptionValue("D", outputDexFile + ".dump");
|
dumpFileName = commandLine.getOptionValue("D", outputDexFile + ".dump");
|
||||||
break;
|
break;
|
||||||
@ -184,6 +190,8 @@ public class main {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Opcode.updateMapsForApiLevel(apiLevel);
|
||||||
|
|
||||||
DexFile dexFile = new DexFile();
|
DexFile dexFile = new DexFile();
|
||||||
|
|
||||||
boolean errors = false;
|
boolean errors = false;
|
||||||
@ -383,6 +391,13 @@ public class main {
|
|||||||
" cause dalvik to reject the class")
|
" cause dalvik to reject the class")
|
||||||
.create("x");
|
.create("x");
|
||||||
|
|
||||||
|
Option apiLevelOption = OptionBuilder.withLongOpt("api-level")
|
||||||
|
.withDescription("The numeric api-level of the file to generate, e.g. 14 for ICS. If not " +
|
||||||
|
"specified, it defaults to 14 (ICS).")
|
||||||
|
.hasArg()
|
||||||
|
.withArgName("API_LEVEL")
|
||||||
|
.create("a");
|
||||||
|
|
||||||
Option dumpOption = OptionBuilder.withLongOpt("dump-to")
|
Option dumpOption = OptionBuilder.withLongOpt("dump-to")
|
||||||
.withDescription("additionally writes a dump of written dex file to FILE (<dexfile>.dump by default)")
|
.withDescription("additionally writes a dump of written dex file to FILE (<dexfile>.dump by default)")
|
||||||
.hasOptionalArg()
|
.hasOptionalArg()
|
||||||
@ -417,6 +432,7 @@ public class main {
|
|||||||
basicOptions.addOption(helpOption);
|
basicOptions.addOption(helpOption);
|
||||||
basicOptions.addOption(outputOption);
|
basicOptions.addOption(outputOption);
|
||||||
basicOptions.addOption(allowOdexOption);
|
basicOptions.addOption(allowOdexOption);
|
||||||
|
basicOptions.addOption(apiLevelOption);
|
||||||
|
|
||||||
debugOptions.addOption(dumpOption);
|
debugOptions.addOption(dumpOption);
|
||||||
debugOptions.addOption(sortOption);
|
debugOptions.addOption(sortOption);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user