mirror of
https://github.com/revanced/smali.git
synced 2025-05-02 15:44:30 +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;
|
||||
|
||||
import org.apache.commons.cli.*;
|
||||
import org.jf.dexlib.Code.Opcode;
|
||||
import org.jf.dexlib.DexFile;
|
||||
import org.jf.util.ConsoleUtil;
|
||||
import org.jf.util.smaliHelpFormatter;
|
||||
@ -108,6 +109,8 @@ public class main {
|
||||
boolean verify = false;
|
||||
boolean ignoreErrors = false;
|
||||
|
||||
int apiLevel = 14;
|
||||
|
||||
int registerInfo = 0;
|
||||
|
||||
String outputDirectory = "out";
|
||||
@ -208,6 +211,9 @@ public class main {
|
||||
case 'm':
|
||||
noAccessorComments = true;
|
||||
break;
|
||||
case 'a':
|
||||
apiLevel = Integer.parseInt(commandLine.getOptionValue("a"));
|
||||
break;
|
||||
case 'N':
|
||||
disassemble = false;
|
||||
break;
|
||||
@ -279,6 +285,8 @@ public class main {
|
||||
bootClassPathDirsArray[i] = bootClassPathDirs.get(i);
|
||||
}
|
||||
|
||||
Opcode.updateMapsForApiLevel(apiLevel);
|
||||
|
||||
baksmali.disassembleDexFile(dexFileFile.getPath(), dexFile, deodex, outputDirectory,
|
||||
bootClassPathDirsArray, bootClassPath, extraBootClassPathEntries.toString(),
|
||||
noParameterRegisters, useLocalsDirective, useSequentialLabels, outputDebugInfo, addCodeOffsets,
|
||||
@ -415,6 +423,13 @@ public class main {
|
||||
.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 14 (ICS).")
|
||||
.hasArg()
|
||||
.withArgName("API_LEVEL")
|
||||
.create("a");
|
||||
|
||||
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")
|
||||
@ -464,6 +479,7 @@ public class main {
|
||||
basicOptions.addOption(classPathDirOption);
|
||||
basicOptions.addOption(codeOffsetOption);
|
||||
basicOptions.addOption(noAccessorCommentsOption);
|
||||
basicOptions.addOption(apiLevelOption);
|
||||
|
||||
debugOptions.addOption(dumpOption);
|
||||
debugOptions.addOption(ignoreErrorsOption);
|
||||
|
@ -73,7 +73,12 @@ public class Instruction21c extends InstructionWithReference implements SingleRe
|
||||
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||
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);
|
||||
|
@ -64,7 +64,12 @@ public class Instruction22c extends InstructionWithReference implements TwoRegis
|
||||
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||
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);
|
||||
|
@ -95,7 +95,12 @@ public class Instruction35c extends InstructionWithReference implements FiveRegi
|
||||
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||
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);
|
||||
|
@ -81,7 +81,12 @@ public class Instruction3rc extends InstructionWithReference implements Register
|
||||
|
||||
protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) {
|
||||
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);
|
||||
|
@ -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 String name;
|
||||
public final ReferenceType referenceType;
|
||||
@ -435,7 +476,7 @@ public enum Opcode
|
||||
}
|
||||
|
||||
public final boolean hasJumboOpcode() {
|
||||
return jumboOpcode != -1;
|
||||
return jumboOpcode != -1 && Opcode.getOpcodeByValue(jumboOpcode) != null;
|
||||
}
|
||||
|
||||
public final Opcode getJumboOpcode() {
|
||||
|
@ -458,10 +458,13 @@ public class CodeItem extends Item<CodeItem> {
|
||||
InstructionWithJumboVariant instructionWithJumboVariant =
|
||||
(InstructionWithJumboVariant)referenceInstruction;
|
||||
|
||||
replaceInstructionAtAddress(currentCodeAddress,
|
||||
instructionWithJumboVariant.makeJumbo());
|
||||
didSomething = true;
|
||||
break;
|
||||
Instruction jumboInstruction = instructionWithJumboVariant.makeJumbo();
|
||||
if (jumboInstruction != null) {
|
||||
replaceInstructionAtAddress(currentCodeAddress,
|
||||
instructionWithJumboVariant.makeJumbo());
|
||||
didSomething = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,7 @@ import org.antlr.runtime.*;
|
||||
import org.antlr.runtime.tree.CommonTree;
|
||||
import org.antlr.runtime.tree.CommonTreeNodeStream;
|
||||
import org.apache.commons.cli.*;
|
||||
import org.jf.dexlib.Code.Opcode;
|
||||
import org.jf.dexlib.CodeItem;
|
||||
import org.jf.dexlib.DexFile;
|
||||
import org.jf.dexlib.Util.ByteArrayAnnotatedOutput;
|
||||
@ -106,6 +107,8 @@ public class main {
|
||||
boolean oldLexer = false;
|
||||
boolean printTokens = false;
|
||||
|
||||
int apiLevel = 14;
|
||||
|
||||
String outputDexFile = "out.dex";
|
||||
String dumpFileName = null;
|
||||
|
||||
@ -136,6 +139,9 @@ public class main {
|
||||
case 'x':
|
||||
allowOdex = true;
|
||||
break;
|
||||
case 'a':
|
||||
apiLevel = Integer.parseInt(commandLine.getOptionValue("a"));
|
||||
break;
|
||||
case 'D':
|
||||
dumpFileName = commandLine.getOptionValue("D", outputDexFile + ".dump");
|
||||
break;
|
||||
@ -184,6 +190,8 @@ public class main {
|
||||
}
|
||||
}
|
||||
|
||||
Opcode.updateMapsForApiLevel(apiLevel);
|
||||
|
||||
DexFile dexFile = new DexFile();
|
||||
|
||||
boolean errors = false;
|
||||
@ -383,6 +391,13 @@ public class main {
|
||||
" cause dalvik to reject the class")
|
||||
.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")
|
||||
.withDescription("additionally writes a dump of written dex file to FILE (<dexfile>.dump by default)")
|
||||
.hasOptionalArg()
|
||||
@ -417,6 +432,7 @@ public class main {
|
||||
basicOptions.addOption(helpOption);
|
||||
basicOptions.addOption(outputOption);
|
||||
basicOptions.addOption(allowOdexOption);
|
||||
basicOptions.addOption(apiLevelOption);
|
||||
|
||||
debugOptions.addOption(dumpOption);
|
||||
debugOptions.addOption(sortOption);
|
||||
|
Loading…
x
Reference in New Issue
Block a user