mirror of
https://github.com/skylot/jadx.git
synced 2024-10-07 10:03:27 +00:00
feat: add option for hexadecimal integer format globally (PR #1869)
* option for hexadecimal integer format globally * fix i18n strings, update readme --------- Co-authored-by: Skylot <skylot@gmail.com>
This commit is contained in:
parent
ccdbb1d62c
commit
63ad7fb128
@ -124,7 +124,6 @@ options:
|
||||
'overwrite' - don't read, always save
|
||||
'ignore' - don't read and don't save
|
||||
--deobf-use-sourcename - use source file name as class name alias
|
||||
--deobf-parse-kotlin-metadata - parse kotlin metadata to class and package names
|
||||
--deobf-res-name-source - better name source for resources:
|
||||
'auto' - automatically select best name (default)
|
||||
'resources' - use resources names
|
||||
@ -136,6 +135,10 @@ options:
|
||||
'printable' - remove non-printable chars from identifiers,
|
||||
or single 'none' - to disable all renames
|
||||
or single 'all' - to enable all (default)
|
||||
--integer-format - how integers are displayed:
|
||||
'auto' - automatically select (default)
|
||||
'decimal' - use decimal
|
||||
'hexadecimal' - use hexadecimal
|
||||
--fs-case-sensitive - treat filesystem as case sensitive, false by default
|
||||
--cfg - save methods control flow graph to dot file
|
||||
--raw-cfg - save methods control flow graph (use raw instructions)
|
||||
|
@ -24,6 +24,7 @@ import jadx.api.JadxArgs.RenameEnum;
|
||||
import jadx.api.JadxArgs.UseKotlinMethodsForVarNames;
|
||||
import jadx.api.JadxDecompiler;
|
||||
import jadx.api.args.GeneratedRenamesMappingFileMode;
|
||||
import jadx.api.args.IntegerFormat;
|
||||
import jadx.api.args.ResourceNameSource;
|
||||
import jadx.api.args.UserRenamesMappingsMode;
|
||||
import jadx.core.utils.exceptions.JadxException;
|
||||
@ -186,6 +187,16 @@ public class JadxCLIArgs {
|
||||
)
|
||||
protected Set<RenameEnum> renameFlags = EnumSet.allOf(RenameEnum.class);
|
||||
|
||||
@Parameter(
|
||||
names = { "--integer-format" },
|
||||
description = "how integers are displayed:"
|
||||
+ "\n 'auto' - automatically select (default)"
|
||||
+ "\n 'decimal' - use decimal"
|
||||
+ "\n 'hexadecimal' - use hexadecimal",
|
||||
converter = IntegerFormatConverter.class
|
||||
)
|
||||
protected IntegerFormat integerFormat = IntegerFormat.AUTO;
|
||||
|
||||
@Parameter(names = { "--fs-case-sensitive" }, description = "treat filesystem as case sensitive, false by default")
|
||||
protected boolean fsCaseSensitive = false;
|
||||
|
||||
@ -318,6 +329,7 @@ public class JadxCLIArgs {
|
||||
args.setRenameFlags(renameFlags);
|
||||
args.setFsCaseSensitive(fsCaseSensitive);
|
||||
args.setCommentsLevel(commentsLevel);
|
||||
args.setIntegerFormat(integerFormat);
|
||||
args.setUseDxInput(useDx);
|
||||
args.setPluginOptions(pluginOptions);
|
||||
return args;
|
||||
@ -447,6 +459,10 @@ public class JadxCLIArgs {
|
||||
return useKotlinMethodsForVarNames;
|
||||
}
|
||||
|
||||
public IntegerFormat getIntegerFormat() {
|
||||
return integerFormat;
|
||||
}
|
||||
|
||||
public boolean isEscapeUnicode() {
|
||||
return escapeUnicode;
|
||||
}
|
||||
@ -564,6 +580,12 @@ public class JadxCLIArgs {
|
||||
}
|
||||
}
|
||||
|
||||
public static class IntegerFormatConverter extends BaseEnumConverter<IntegerFormat> {
|
||||
public IntegerFormatConverter() {
|
||||
super(IntegerFormat::valueOf, IntegerFormat::values);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract static class BaseEnumConverter<E extends Enum<E>> implements IStringConverter<E> {
|
||||
private final Function<String, E> parse;
|
||||
private final Supplier<E[]> values;
|
||||
|
@ -17,6 +17,7 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import jadx.api.args.GeneratedRenamesMappingFileMode;
|
||||
import jadx.api.args.IntegerFormat;
|
||||
import jadx.api.args.ResourceNameSource;
|
||||
import jadx.api.args.UserRenamesMappingsMode;
|
||||
import jadx.api.data.ICodeData;
|
||||
@ -132,6 +133,8 @@ public class JadxArgs implements Closeable {
|
||||
|
||||
private CommentsLevel commentsLevel = CommentsLevel.INFO;
|
||||
|
||||
private IntegerFormat integerFormat = IntegerFormat.AUTO;
|
||||
|
||||
private boolean useDxInput = false;
|
||||
|
||||
public enum UseKotlinMethodsForVarNames {
|
||||
@ -591,6 +594,14 @@ public class JadxArgs implements Closeable {
|
||||
this.commentsLevel = commentsLevel;
|
||||
}
|
||||
|
||||
public IntegerFormat getIntegerFormat() {
|
||||
return integerFormat;
|
||||
}
|
||||
|
||||
public void setIntegerFormat(IntegerFormat format) {
|
||||
this.integerFormat = format;
|
||||
}
|
||||
|
||||
public boolean isUseDxInput() {
|
||||
return useDxInput;
|
||||
}
|
||||
@ -635,7 +646,7 @@ public class JadxArgs implements Closeable {
|
||||
+ insertDebugLines + extractFinally
|
||||
+ debugInfo + useSourceNameAsClassAlias + escapeUnicode + replaceConsts
|
||||
+ respectBytecodeAccModifiers + fsCaseSensitive + renameFlags
|
||||
+ commentsLevel + useDxInput;
|
||||
+ commentsLevel + useDxInput + integerFormat;
|
||||
return FileUtils.md5Sum(argStr);
|
||||
}
|
||||
|
||||
|
11
jadx-core/src/main/java/jadx/api/args/IntegerFormat.java
Normal file
11
jadx-core/src/main/java/jadx/api/args/IntegerFormat.java
Normal file
@ -0,0 +1,11 @@
|
||||
package jadx.api.args;
|
||||
|
||||
public enum IntegerFormat {
|
||||
AUTO,
|
||||
DECIMAL,
|
||||
HEXADECIMAL;
|
||||
|
||||
public boolean isHexadecimal() {
|
||||
return this == HEXADECIMAL;
|
||||
}
|
||||
}
|
@ -146,6 +146,8 @@ public class AnnotationGen {
|
||||
code.add("null");
|
||||
return;
|
||||
}
|
||||
|
||||
StringUtils stringUtils = getStringUtils();
|
||||
Object value = encodedValue.getValue();
|
||||
switch (encodedValue.getType()) {
|
||||
case ENCODED_NULL:
|
||||
@ -155,28 +157,28 @@ public class AnnotationGen {
|
||||
code.add(Boolean.TRUE.equals(value) ? "true" : "false");
|
||||
break;
|
||||
case ENCODED_BYTE:
|
||||
code.add(TypeGen.formatByte((Byte) value, false));
|
||||
code.add(stringUtils.formatByte((Byte) value, false));
|
||||
break;
|
||||
case ENCODED_SHORT:
|
||||
code.add(TypeGen.formatShort((Short) value, false));
|
||||
code.add(stringUtils.formatShort((Short) value, false));
|
||||
break;
|
||||
case ENCODED_CHAR:
|
||||
code.add(getStringUtils().unescapeChar((Character) value));
|
||||
code.add(stringUtils.unescapeChar((Character) value));
|
||||
break;
|
||||
case ENCODED_INT:
|
||||
code.add(TypeGen.formatInteger((Integer) value, false));
|
||||
code.add(stringUtils.formatInteger((Integer) value, false));
|
||||
break;
|
||||
case ENCODED_LONG:
|
||||
code.add(TypeGen.formatLong((Long) value, false));
|
||||
code.add(stringUtils.formatLong((Long) value, false));
|
||||
break;
|
||||
case ENCODED_FLOAT:
|
||||
code.add(TypeGen.formatFloat((Float) value));
|
||||
code.add(StringUtils.formatFloat((Float) value));
|
||||
break;
|
||||
case ENCODED_DOUBLE:
|
||||
code.add(TypeGen.formatDouble((Double) value));
|
||||
code.add(StringUtils.formatDouble((Double) value));
|
||||
break;
|
||||
case ENCODED_STRING:
|
||||
code.add(getStringUtils().unescapeString((String) value));
|
||||
code.add(stringUtils.unescapeString((String) value));
|
||||
break;
|
||||
case ENCODED_TYPE:
|
||||
classGen.useType(code, ArgType.parse((String) value));
|
||||
|
@ -19,6 +19,7 @@ import jadx.api.CommentsLevel;
|
||||
import jadx.api.ICodeInfo;
|
||||
import jadx.api.ICodeWriter;
|
||||
import jadx.api.JadxArgs;
|
||||
import jadx.api.args.IntegerFormat;
|
||||
import jadx.api.metadata.annotations.NodeEnd;
|
||||
import jadx.api.plugins.input.data.AccessFlags;
|
||||
import jadx.api.plugins.input.data.annotations.EncodedType;
|
||||
@ -59,6 +60,7 @@ public class ClassGen {
|
||||
private final boolean fallback;
|
||||
private final boolean useImports;
|
||||
private final boolean showInconsistentCode;
|
||||
private final IntegerFormat integerFormat;
|
||||
|
||||
private final Set<ClassInfo> imports = new HashSet<>();
|
||||
private int clsDeclOffset;
|
||||
@ -69,19 +71,22 @@ public class ClassGen {
|
||||
private NameGen outerNameGen;
|
||||
|
||||
public ClassGen(ClassNode cls, JadxArgs jadxArgs) {
|
||||
this(cls, null, jadxArgs.isUseImports(), jadxArgs.isFallbackMode(), jadxArgs.isShowInconsistentCode());
|
||||
this(cls, null, jadxArgs.isUseImports(), jadxArgs.isFallbackMode(), jadxArgs.isShowInconsistentCode(), jadxArgs.getIntegerFormat());
|
||||
}
|
||||
|
||||
public ClassGen(ClassNode cls, ClassGen parentClsGen) {
|
||||
this(cls, parentClsGen, parentClsGen.useImports, parentClsGen.fallback, parentClsGen.showInconsistentCode);
|
||||
this(cls, parentClsGen, parentClsGen.useImports, parentClsGen.fallback, parentClsGen.showInconsistentCode,
|
||||
parentClsGen.integerFormat);
|
||||
}
|
||||
|
||||
public ClassGen(ClassNode cls, ClassGen parentClsGen, boolean useImports, boolean fallback, boolean showBadCode) {
|
||||
public ClassGen(ClassNode cls, ClassGen parentClsGen, boolean useImports, boolean fallback, boolean showBadCode,
|
||||
IntegerFormat integerFormat) {
|
||||
this.cls = cls;
|
||||
this.parentGen = parentClsGen;
|
||||
this.fallback = fallback;
|
||||
this.useImports = useImports;
|
||||
this.showInconsistentCode = showBadCode;
|
||||
this.integerFormat = integerFormat;
|
||||
|
||||
this.annotationGen = new AnnotationGen(cls, this);
|
||||
}
|
||||
@ -424,10 +429,7 @@ public class ClassGen {
|
||||
Object val = EncodedValueUtils.convertToConstValue(constVal);
|
||||
if (val instanceof LiteralArg) {
|
||||
long lit = ((LiteralArg) val).getLiteral();
|
||||
if (!AndroidResourcesUtils.handleResourceFieldValue(cls, code, lit, f.getType())) {
|
||||
// force literal type to be same as field (java bytecode can use different type)
|
||||
code.add(TypeGen.literalToString(lit, f.getType(), cls, fallback));
|
||||
}
|
||||
code.add(getIntegerString(lit, f.getType()));
|
||||
} else {
|
||||
annotationGen.encodeValue(cls.root(), code, constVal);
|
||||
}
|
||||
@ -437,6 +439,14 @@ public class ClassGen {
|
||||
code.add(';');
|
||||
}
|
||||
|
||||
private String getIntegerString(long lit, ArgType type) {
|
||||
if (integerFormat != IntegerFormat.DECIMAL && AndroidResourcesUtils.isResourceFieldValue(cls, type)) {
|
||||
return String.format("0x%08x", lit);
|
||||
}
|
||||
// force literal type to be same as field (java bytecode can use different type)
|
||||
return TypeGen.literalToString(lit, type, cls, fallback);
|
||||
}
|
||||
|
||||
private boolean isFieldsPresents() {
|
||||
for (FieldNode field : cls.getFields()) {
|
||||
if (!field.contains(AFlag.DONT_GENERATE)) {
|
||||
|
@ -13,6 +13,7 @@ import org.slf4j.LoggerFactory;
|
||||
import jadx.api.CommentsLevel;
|
||||
import jadx.api.ICodeWriter;
|
||||
import jadx.api.JadxArgs;
|
||||
import jadx.api.args.IntegerFormat;
|
||||
import jadx.api.metadata.annotations.InsnCodeOffset;
|
||||
import jadx.api.metadata.annotations.VarNode;
|
||||
import jadx.api.plugins.input.data.AccessFlags;
|
||||
@ -548,7 +549,7 @@ public class MethodGen {
|
||||
* Return fallback variant of method codegen
|
||||
*/
|
||||
public static MethodGen getFallbackMethodGen(MethodNode mth) {
|
||||
ClassGen clsGen = new ClassGen(mth.getParentClass(), null, false, true, true);
|
||||
ClassGen clsGen = new ClassGen(mth.getParentClass(), null, false, true, true, IntegerFormat.AUTO);
|
||||
return new MethodGen(clsGen, mth);
|
||||
}
|
||||
|
||||
|
@ -73,17 +73,17 @@ public class TypeGen {
|
||||
case CHAR:
|
||||
return stringUtils.unescapeChar((char) lit, cast);
|
||||
case BYTE:
|
||||
return formatByte(lit, cast);
|
||||
return stringUtils.formatByte(lit, cast);
|
||||
case SHORT:
|
||||
return formatShort(lit, cast);
|
||||
return stringUtils.formatShort(lit, cast);
|
||||
case INT:
|
||||
return formatInteger(lit, cast);
|
||||
return stringUtils.formatInteger(lit, cast);
|
||||
case LONG:
|
||||
return formatLong(lit, cast);
|
||||
return stringUtils.formatLong(lit, cast);
|
||||
case FLOAT:
|
||||
return formatFloat(Float.intBitsToFloat((int) lit));
|
||||
return StringUtils.formatFloat(Float.intBitsToFloat((int) lit));
|
||||
case DOUBLE:
|
||||
return formatDouble(Double.longBitsToDouble(lit));
|
||||
return StringUtils.formatDouble(Double.longBitsToDouble(lit));
|
||||
|
||||
case OBJECT:
|
||||
case ARRAY:
|
||||
@ -134,95 +134,4 @@ public class TypeGen {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static String formatShort(long l, boolean cast) {
|
||||
if (l == Short.MAX_VALUE) {
|
||||
return "Short.MAX_VALUE";
|
||||
}
|
||||
if (l == Short.MIN_VALUE) {
|
||||
return "Short.MIN_VALUE";
|
||||
}
|
||||
String str = Long.toString(l);
|
||||
return cast ? "(short) " + str : str;
|
||||
}
|
||||
|
||||
public static String formatByte(long l, boolean cast) {
|
||||
if (l == Byte.MAX_VALUE) {
|
||||
return "Byte.MAX_VALUE";
|
||||
}
|
||||
if (l == Byte.MIN_VALUE) {
|
||||
return "Byte.MIN_VALUE";
|
||||
}
|
||||
String str = Long.toString(l);
|
||||
return cast ? "(byte) " + str : str;
|
||||
}
|
||||
|
||||
public static String formatInteger(long l, boolean cast) {
|
||||
if (l == Integer.MAX_VALUE) {
|
||||
return "Integer.MAX_VALUE";
|
||||
}
|
||||
if (l == Integer.MIN_VALUE) {
|
||||
return "Integer.MIN_VALUE";
|
||||
}
|
||||
String str = Long.toString(l);
|
||||
return cast ? "(int) " + str : str;
|
||||
}
|
||||
|
||||
public static String formatLong(long l, boolean cast) {
|
||||
if (l == Long.MAX_VALUE) {
|
||||
return "Long.MAX_VALUE";
|
||||
}
|
||||
if (l == Long.MIN_VALUE) {
|
||||
return "Long.MIN_VALUE";
|
||||
}
|
||||
String str = Long.toString(l);
|
||||
if (cast || Math.abs(l) >= Integer.MAX_VALUE) {
|
||||
return str + 'L';
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
public static String formatDouble(double d) {
|
||||
if (Double.isNaN(d)) {
|
||||
return "Double.NaN";
|
||||
}
|
||||
if (d == Double.NEGATIVE_INFINITY) {
|
||||
return "Double.NEGATIVE_INFINITY";
|
||||
}
|
||||
if (d == Double.POSITIVE_INFINITY) {
|
||||
return "Double.POSITIVE_INFINITY";
|
||||
}
|
||||
if (d == Double.MIN_VALUE) {
|
||||
return "Double.MIN_VALUE";
|
||||
}
|
||||
if (d == Double.MAX_VALUE) {
|
||||
return "Double.MAX_VALUE";
|
||||
}
|
||||
if (d == Double.MIN_NORMAL) {
|
||||
return "Double.MIN_NORMAL";
|
||||
}
|
||||
return Double.toString(d) + 'd';
|
||||
}
|
||||
|
||||
public static String formatFloat(float f) {
|
||||
if (Float.isNaN(f)) {
|
||||
return "Float.NaN";
|
||||
}
|
||||
if (f == Float.NEGATIVE_INFINITY) {
|
||||
return "Float.NEGATIVE_INFINITY";
|
||||
}
|
||||
if (f == Float.POSITIVE_INFINITY) {
|
||||
return "Float.POSITIVE_INFINITY";
|
||||
}
|
||||
if (f == Float.MIN_VALUE) {
|
||||
return "Float.MIN_VALUE";
|
||||
}
|
||||
if (f == Float.MAX_VALUE) {
|
||||
return "Float.MAX_VALUE";
|
||||
}
|
||||
if (f == Float.MIN_NORMAL) {
|
||||
return "Float.MIN_NORMAL";
|
||||
}
|
||||
return Float.toString(f) + 'f';
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import java.util.function.IntConsumer;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import jadx.api.JadxArgs;
|
||||
import jadx.api.args.IntegerFormat;
|
||||
import jadx.core.deobf.NameMapper;
|
||||
|
||||
public class StringUtils {
|
||||
@ -19,9 +20,15 @@ public class StringUtils {
|
||||
}
|
||||
|
||||
private final boolean escapeUnicode;
|
||||
private final IntegerFormat integerFormat;
|
||||
|
||||
public StringUtils(JadxArgs args) {
|
||||
this.escapeUnicode = args.isEscapeUnicode();
|
||||
this.integerFormat = args.getIntegerFormat();
|
||||
}
|
||||
|
||||
public IntegerFormat getIntegerFormat() {
|
||||
return integerFormat;
|
||||
}
|
||||
|
||||
public static void visitCodePoints(String str, IntConsumer visitor) {
|
||||
@ -370,4 +377,102 @@ public class StringUtils {
|
||||
public static String getDateText() {
|
||||
return new SimpleDateFormat("HH:mm:ss").format(new Date());
|
||||
}
|
||||
|
||||
private String toFormatString(long l) {
|
||||
if (integerFormat.isHexadecimal()) {
|
||||
return "0x" + Long.toHexString(l);
|
||||
}
|
||||
return Long.toString(l);
|
||||
}
|
||||
|
||||
public String formatShort(long l, boolean cast) {
|
||||
if (l == Short.MAX_VALUE) {
|
||||
return "Short.MAX_VALUE";
|
||||
}
|
||||
if (l == Short.MIN_VALUE) {
|
||||
return "Short.MIN_VALUE";
|
||||
}
|
||||
String str = toFormatString(l);
|
||||
return cast ? "(short) " + str : str;
|
||||
}
|
||||
|
||||
public String formatByte(long l, boolean cast) {
|
||||
if (l == Byte.MAX_VALUE) {
|
||||
return "Byte.MAX_VALUE";
|
||||
}
|
||||
if (l == Byte.MIN_VALUE) {
|
||||
return "Byte.MIN_VALUE";
|
||||
}
|
||||
String str = toFormatString(l);
|
||||
return cast ? "(byte) " + str : str;
|
||||
}
|
||||
|
||||
public String formatInteger(long l, boolean cast) {
|
||||
if (l == Integer.MAX_VALUE) {
|
||||
return "Integer.MAX_VALUE";
|
||||
}
|
||||
if (l == Integer.MIN_VALUE) {
|
||||
return "Integer.MIN_VALUE";
|
||||
}
|
||||
String str = toFormatString(l);
|
||||
return cast ? "(int) " + str : str;
|
||||
}
|
||||
|
||||
public String formatLong(long l, boolean cast) {
|
||||
if (l == Long.MAX_VALUE) {
|
||||
return "Long.MAX_VALUE";
|
||||
}
|
||||
if (l == Long.MIN_VALUE) {
|
||||
return "Long.MIN_VALUE";
|
||||
}
|
||||
String str = toFormatString(l);
|
||||
if (cast || Math.abs(l) >= Integer.MAX_VALUE) {
|
||||
return str + 'L';
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
public static String formatDouble(double d) {
|
||||
if (Double.isNaN(d)) {
|
||||
return "Double.NaN";
|
||||
}
|
||||
if (d == Double.NEGATIVE_INFINITY) {
|
||||
return "Double.NEGATIVE_INFINITY";
|
||||
}
|
||||
if (d == Double.POSITIVE_INFINITY) {
|
||||
return "Double.POSITIVE_INFINITY";
|
||||
}
|
||||
if (d == Double.MIN_VALUE) {
|
||||
return "Double.MIN_VALUE";
|
||||
}
|
||||
if (d == Double.MAX_VALUE) {
|
||||
return "Double.MAX_VALUE";
|
||||
}
|
||||
if (d == Double.MIN_NORMAL) {
|
||||
return "Double.MIN_NORMAL";
|
||||
}
|
||||
return Double.toString(d) + 'd';
|
||||
}
|
||||
|
||||
public static String formatFloat(float f) {
|
||||
if (Float.isNaN(f)) {
|
||||
return "Float.NaN";
|
||||
}
|
||||
if (f == Float.NEGATIVE_INFINITY) {
|
||||
return "Float.NEGATIVE_INFINITY";
|
||||
}
|
||||
if (f == Float.POSITIVE_INFINITY) {
|
||||
return "Float.POSITIVE_INFINITY";
|
||||
}
|
||||
if (f == Float.MIN_VALUE) {
|
||||
return "Float.MIN_VALUE";
|
||||
}
|
||||
if (f == Float.MAX_VALUE) {
|
||||
return "Float.MAX_VALUE";
|
||||
}
|
||||
if (f == Float.MIN_NORMAL) {
|
||||
return "Float.MIN_NORMAL";
|
||||
}
|
||||
return Float.toString(f) + 'f';
|
||||
}
|
||||
}
|
||||
|
@ -76,12 +76,8 @@ public class AndroidResourcesUtils {
|
||||
/**
|
||||
* Force hex format for Android resources ids
|
||||
*/
|
||||
public static boolean handleResourceFieldValue(ClassNode cls, ICodeWriter code, long lit, ArgType type) {
|
||||
if (type.equals(ArgType.INT) && isResourceClass(cls)) {
|
||||
code.add(String.format("0x%08x", lit));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
public static boolean isResourceFieldValue(ClassNode cls, ArgType type) {
|
||||
return type.equals(ArgType.INT) && isResourceClass(cls);
|
||||
}
|
||||
|
||||
public static boolean isResourceClass(ClassNode cls) {
|
||||
|
@ -37,7 +37,6 @@ import jadx.api.plugins.input.insns.InsnData;
|
||||
import jadx.api.plugins.input.insns.InsnIndexType;
|
||||
import jadx.api.plugins.input.insns.Opcode;
|
||||
import jadx.api.plugins.input.insns.custom.ISwitchPayload;
|
||||
import jadx.core.codegen.TypeGen;
|
||||
import jadx.core.dex.attributes.AttributeStorage;
|
||||
import jadx.core.dex.instructions.IndexInsnNode;
|
||||
import jadx.core.dex.instructions.InsnDecoder;
|
||||
@ -48,6 +47,7 @@ import jadx.core.dex.instructions.args.RegisterArg;
|
||||
import jadx.core.dex.nodes.ClassNode;
|
||||
import jadx.core.dex.nodes.InsnNode;
|
||||
import jadx.core.dex.nodes.MethodNode;
|
||||
import jadx.core.utils.StringUtils;
|
||||
import jadx.core.utils.Utils;
|
||||
import jadx.core.utils.exceptions.JadxRuntimeException;
|
||||
|
||||
@ -593,6 +593,7 @@ public class Smali {
|
||||
}
|
||||
|
||||
private void writeEncodedValue(SmaliWriter smali, EncodedValue value, boolean wrapArray) {
|
||||
StringUtils stringUtils = smali.getClassNode().root().getStringUtils();
|
||||
switch (value.getType()) {
|
||||
case ENCODED_ARRAY:
|
||||
smali.add("{");
|
||||
@ -624,28 +625,28 @@ public class Smali {
|
||||
writeAnnotation(smali, (IAnnotation) value.getValue());
|
||||
break;
|
||||
case ENCODED_BYTE:
|
||||
smali.add(TypeGen.formatByte((Byte) value.getValue(), false));
|
||||
smali.add(stringUtils.formatByte((Byte) value.getValue(), false));
|
||||
break;
|
||||
case ENCODED_SHORT:
|
||||
smali.add(TypeGen.formatShort((Short) value.getValue(), false));
|
||||
smali.add(stringUtils.formatShort((Short) value.getValue(), false));
|
||||
break;
|
||||
case ENCODED_CHAR:
|
||||
smali.add(smali.getClassNode().root().getStringUtils().unescapeChar((Character) value.getValue()));
|
||||
smali.add(stringUtils.unescapeChar((Character) value.getValue()));
|
||||
break;
|
||||
case ENCODED_INT:
|
||||
smali.add(TypeGen.formatInteger((Integer) value.getValue(), false));
|
||||
smali.add(stringUtils.formatInteger((Integer) value.getValue(), false));
|
||||
break;
|
||||
case ENCODED_LONG:
|
||||
smali.add(TypeGen.formatLong((Long) value.getValue(), false));
|
||||
smali.add(stringUtils.formatLong((Long) value.getValue(), false));
|
||||
break;
|
||||
case ENCODED_FLOAT:
|
||||
smali.add(TypeGen.formatFloat((Float) value.getValue()));
|
||||
smali.add(StringUtils.formatFloat((Float) value.getValue()));
|
||||
break;
|
||||
case ENCODED_DOUBLE:
|
||||
smali.add(TypeGen.formatDouble((Double) value.getValue()));
|
||||
smali.add(StringUtils.formatDouble((Double) value.getValue()));
|
||||
break;
|
||||
case ENCODED_STRING:
|
||||
smali.add(smali.getClassNode().root().getStringUtils().unescapeString((String) value.getValue()));
|
||||
smali.add(stringUtils.unescapeString((String) value.getValue()));
|
||||
break;
|
||||
case ENCODED_TYPE:
|
||||
smali.add(ArgType.parse((String) value.getValue()) + ".class");
|
||||
|
@ -26,6 +26,7 @@ import jadx.api.CommentsLevel;
|
||||
import jadx.api.DecompilationMode;
|
||||
import jadx.api.JadxArgs;
|
||||
import jadx.api.args.GeneratedRenamesMappingFileMode;
|
||||
import jadx.api.args.IntegerFormat;
|
||||
import jadx.api.args.ResourceNameSource;
|
||||
import jadx.api.args.UserRenamesMappingsMode;
|
||||
import jadx.cli.JadxCLIArgs;
|
||||
@ -652,6 +653,10 @@ public class JadxSettings extends JadxCLIArgs {
|
||||
return lineNumbersMode;
|
||||
}
|
||||
|
||||
public void setIntegerFormat(IntegerFormat format) {
|
||||
this.integerFormat = format;
|
||||
}
|
||||
|
||||
public void setLineNumbersMode(LineNumbersMode lineNumbersMode) {
|
||||
this.lineNumbersMode = lineNumbersMode;
|
||||
}
|
||||
|
@ -63,6 +63,7 @@ import jadx.api.DecompilationMode;
|
||||
import jadx.api.JadxArgs;
|
||||
import jadx.api.JadxArgs.UseKotlinMethodsForVarNames;
|
||||
import jadx.api.args.GeneratedRenamesMappingFileMode;
|
||||
import jadx.api.args.IntegerFormat;
|
||||
import jadx.api.args.ResourceNameSource;
|
||||
import jadx.api.plugins.options.JadxPluginOptions;
|
||||
import jadx.api.plugins.options.OptionDescription;
|
||||
@ -758,6 +759,13 @@ public class JadxSettingsWindow extends JDialog {
|
||||
needReload();
|
||||
});
|
||||
|
||||
JComboBox<IntegerFormat> integerFormat = new JComboBox<>(IntegerFormat.values());
|
||||
integerFormat.setSelectedItem(settings.getIntegerFormat());
|
||||
integerFormat.addActionListener(e -> {
|
||||
settings.setIntegerFormat((IntegerFormat) integerFormat.getSelectedItem());
|
||||
needReload();
|
||||
});
|
||||
|
||||
SettingsGroup group = new SettingsGroup(NLS.str("preferences.other"));
|
||||
group.addRow(NLS.str("preferences.language"), languageCbx);
|
||||
group.addRow(NLS.str("preferences.lineNumbersMode"), lineNumbersMode);
|
||||
@ -766,6 +774,7 @@ public class JadxSettingsWindow extends JDialog {
|
||||
group.addRow(NLS.str("preferences.check_for_updates"), update);
|
||||
group.addRow(NLS.str("preferences.cfg"), cfg);
|
||||
group.addRow(NLS.str("preferences.raw_cfg"), rawCfg);
|
||||
group.addRow(NLS.str("preferences.integerFormat"), integerFormat);
|
||||
return group;
|
||||
}
|
||||
|
||||
|
@ -192,6 +192,7 @@ preferences.excludedPackages.button=Bearbeiten
|
||||
preferences.excludedPackages.editDialog=<html>Liste der durch Leerzeichen getrennten Paketnamen, die nicht dekompiliert oder indiziert werden. (spart RAM)<br>z.B. <code>android.support</code></html>
|
||||
preferences.cfg=CFG-Grafiken für Methoden generieren (im 'dot'-Format)
|
||||
preferences.raw_cfg=RAW CFG-Grafiken generieren
|
||||
#preferences.integerFormat=Integer format
|
||||
preferences.font=Schrift ändern
|
||||
preferences.smali_font=Schrifteditor
|
||||
preferences.laf_theme=Thema
|
||||
|
@ -192,6 +192,7 @@ preferences.excludedPackages.button=Edit
|
||||
preferences.excludedPackages.editDialog=<html>List of space separated package names that will not be decompiled or indexed (saves RAM)<br>e.g. <code>android.support</code></html>
|
||||
preferences.cfg=Generate methods CFG graphs (in 'dot' format)
|
||||
preferences.raw_cfg=Generate RAW CFG graphs
|
||||
preferences.integerFormat=Integer format
|
||||
preferences.font=Editor font
|
||||
preferences.smali_font=Smali Editor font
|
||||
preferences.laf_theme=Theme
|
||||
|
@ -192,6 +192,7 @@ preferences.threads=Número de hilos a procesar
|
||||
#preferences.excludedPackages.editDialog=
|
||||
preferences.cfg=Generar methods CFG graphs (in 'dot' format)
|
||||
preferences.raw_cfg=Generate RAW CFG graphs
|
||||
#preferences.integerFormat=Integer format
|
||||
preferences.font=Fuente del editor
|
||||
#preferences.smali_font=
|
||||
#preferences.laf_theme=Theme
|
||||
|
@ -192,6 +192,7 @@ preferences.excludedPackages.button=Edit
|
||||
preferences.excludedPackages.editDialog=<html>RAM 절약을 위해 디컴파일되거나 인덱싱하지 않을 패키지 이름 목록 (공백으로 항목 구분)<br>예: <code>android.support</code></html>
|
||||
preferences.cfg=메소드 CFG 그래프 생성 ('dot' 포맷)
|
||||
preferences.raw_cfg=RAW CFG 그래프 생성
|
||||
#preferences.integerFormat=Integer format
|
||||
preferences.font=에디터 글씨체
|
||||
preferences.smali_font=Smali 에디터 글씨체
|
||||
preferences.laf_theme=테마
|
||||
|
@ -192,6 +192,7 @@ preferences.excludedPackages.button=Editar
|
||||
preferences.excludedPackages.editDialog=<html>Lista espaço de pacotes que não vão ser descompilados ou indexados (economiza RAM)<br>ex: <code>android.support</code></html>
|
||||
preferences.cfg=Gera gráficos de métodos CFG no formato de pontos ('dot')
|
||||
preferences.raw_cfg=Gera gráficos CFG no formato RAW
|
||||
#preferences.integerFormat=Integer format
|
||||
preferences.font=Fonte do editor
|
||||
preferences.smali_font=Fonte do editor de smali
|
||||
preferences.laf_theme=Tema
|
||||
|
@ -192,6 +192,7 @@ preferences.excludedPackages.button=Изменить
|
||||
preferences.excludedPackages.editDialog=<html>Список пакетов, которые не будут декомпилироваться и индексироваться (экономит ОЗУ)<br>например: <code>android.support</code><br>Разделитель - одинарный пробел</html>
|
||||
preferences.cfg=Методы генерации графиков CFG (в "dot" формате)
|
||||
preferences.raw_cfg=Генерировать необработанные графики CFG
|
||||
#preferences.integerFormat=Integer format
|
||||
preferences.font=Шрифт редактора Java
|
||||
preferences.smali_font=Шрифт редактора smali
|
||||
preferences.laf_theme=Тема приложения
|
||||
|
@ -192,6 +192,7 @@ preferences.excludedPackages.button=编辑
|
||||
preferences.excludedPackages.editDialog=<html>排除于反编译或索引的以空格分隔的包名列表(节省 RAM)<br>例如<code>android.support</code></html>
|
||||
preferences.cfg=生成方法的 CFG 图('.dot')
|
||||
preferences.raw_cfg=生成原始的 CFG 图
|
||||
#preferences.integerFormat=Integer format
|
||||
preferences.font=编辑器字体
|
||||
preferences.smali_font=Smali编辑器字体
|
||||
preferences.laf_theme=主题
|
||||
|
@ -192,6 +192,7 @@ preferences.excludedPackages.button=編輯
|
||||
preferences.excludedPackages.editDialog=<html>排除於索引或反編譯外的套件列表 (以空格分隔) (節省 RAM) <br>例如 <code>android.support</code></html>
|
||||
preferences.cfg=產生方法 CFG 圖表 ('dot' 格式)
|
||||
preferences.raw_cfg=產生 RAW CFG 圖表
|
||||
#preferences.integerFormat=Integer format
|
||||
preferences.font=編輯器字型
|
||||
preferences.smali_font=Smali 編輯器字型
|
||||
preferences.laf_theme=主題
|
||||
|
Loading…
Reference in New Issue
Block a user