Skip to content

Commit

Permalink
feat(cli): add options for change log level (#735)
Browse files Browse the repository at this point in the history
  • Loading branch information
skylot committed Aug 8, 2019
1 parent c0194d0 commit bc7a748
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 48 deletions.
15 changes: 9 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,12 @@ options:
-d, --output-dir - output directory
-ds, --output-dir-src - output directory for sources
-dr, --output-dir-res - output directory for resources
-j, --threads-count - processing threads count
-r, --no-res - do not decode resources
-s, --no-src - do not decompile source code
--single-class - decompile a single class
--output-format - can be 'java' or 'json' (default: java)
--output-format - can be 'java' or 'json', default: java
-e, --export-gradle - save as android gradle project
-j, --threads-count - processing threads count, default: 4
--show-bad-code - show inconsistent code (incorrectly decompiled)
--no-imports - disable use of imports, always write entire package name
--no-debug-info - disable debug info
Expand All @@ -85,22 +85,25 @@ options:
--escape-unicode - escape non latin characters in strings (with \u)
--respect-bytecode-access-modifiers - don't change original access modifiers
--deobf - activate deobfuscation
--deobf-min - min length of name, renamed if shorter (default: 3)
--deobf-max - max length of name, renamed if longer (default: 64)
--deobf-min - min length of name, renamed if shorter, default: 3
--deobf-max - max length of name, renamed if longer, default: 64
--deobf-rewrite-cfg - force to save deobfuscation map
--deobf-use-sourcename - use source file name as class name alias
--rename-flags - what to rename, comma-separated, 'case' for system case sensitivity, 'valid' for java identifiers, 'printable' characters, 'none' or 'all'
--rename-flags - what to rename, comma-separated, 'case' for system case sensitivity, 'valid' for java identifiers, 'printable' characters, 'none' or 'all' (default)
--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)
-f, --fallback - make simple dump (using goto instead of 'if', 'for', etc)
-v, --verbose - verbose output
-v, --verbose - verbose output (set --log-level to DEBUG)
-q, --quiet - turn off output (set --log-level to QUIET)
--log-level - set log level, values: QUIET, PROGRESS, ERROR, WARN, INFO, DEBUG, default: PROGRESS
--version - print jadx version
-h, --help - print this help
Example:
jadx -d out classes.dex
jadx --rename-flags "none" classes.dex
jadx --rename-flags "valid,printable" classes.dex
jadx --log-level error app.apk
```
These options also worked on jadx-gui running from command line and override options from preferences dialog

Expand Down
37 changes: 21 additions & 16 deletions jadx-cli/src/main/java/jadx/cli/JCommanderWrapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import java.util.List;
import java.util.Map;

import org.jetbrains.annotations.Nullable;

import com.beust.jcommander.JCommander;
import com.beust.jcommander.ParameterDescription;
import com.beust.jcommander.ParameterException;
Expand Down Expand Up @@ -80,7 +82,10 @@ public void printUsage() {
opt.append(" ").append(p.getNames());
addSpaces(opt, maxNamesLen - opt.length() + 3);
opt.append("- ").append(p.getDescription());
addDefaultValue(args, f, opt);
String defaultValue = getDefaultValue(args, f, opt);
if (defaultValue != null) {
opt.append(", default: ").append(defaultValue);
}
out.println(opt);
}
out.println("Example:");
Expand All @@ -102,26 +107,26 @@ private List<Field> getFields(Class<?> clazz) {
return fieldList;
}

private void addDefaultValue(JadxCLIArgs args, Field f, StringBuilder opt) {
Class<?> fieldType = f.getType();
if (fieldType == int.class) {
try {
int val = f.getInt(args);
opt.append(" (default: ").append(val).append(')');
} catch (Exception e) {
// ignore
@Nullable
private String getDefaultValue(JadxCLIArgs args, Field f, StringBuilder opt) {
try {
Class<?> fieldType = f.getType();
if (fieldType == int.class) {
return Integer.toString(f.getInt(args));
}
}
if (fieldType == String.class) {
try {
String val = (String) f.get(args);
if (fieldType == String.class) {
return (String) f.get(args);
}
if (Enum.class.isAssignableFrom(fieldType)) {
Enum<?> val = (Enum<?>) f.get(args);
if (val != null) {
opt.append(" (default: ").append(val).append(')');
return val.name();
}
} catch (Exception e) {
// ignore
}
} catch (Exception e) {
// ignore
}
return null;
}

private static void addSpaces(StringBuilder str, int count) {
Expand Down
4 changes: 2 additions & 2 deletions jadx-cli/src/main/java/jadx/cli/JadxCLI.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ static int processAndSave(JadxCLIArgs inputArgs) {
int errorsCount = jadx.getErrorsCount();
if (errorsCount != 0) {
jadx.printErrorsReport();
LOG.error("finished with errors");
LOG.error("finished with errors, count: {}", errorsCount);
} else {
LOG.info("done");
}
return errorsCount;
return 0;
}
}
39 changes: 19 additions & 20 deletions jadx-cli/src/main/java/jadx/cli/JadxCLIArgs.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,9 @@
import java.util.Set;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.beust.jcommander.IStringConverter;
import com.beust.jcommander.Parameter;

import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.Appender;

import jadx.api.JadxArgs;
import jadx.api.JadxArgs.RenameEnum;
import jadx.api.JadxDecompiler;
Expand Down Expand Up @@ -114,9 +108,19 @@ public class JadxCLIArgs {
@Parameter(names = { "-f", "--fallback" }, description = "make simple dump (using goto instead of 'if', 'for', etc)")
protected boolean fallbackMode = false;

@Parameter(names = { "-v", "--verbose" }, description = "verbose output")
@Parameter(names = { "-v", "--verbose" }, description = "verbose output (set --log-level to DEBUG)")
protected boolean verbose = false;

@Parameter(names = { "-q", "--quiet" }, description = "turn off output (set --log-level to QUIET)")
protected boolean quiet = false;

@Parameter(
names = { "--log-level" },
description = "set log level, values: QUIET, PROGRESS, ERROR, WARN, INFO, DEBUG",
converter = LogHelper.LogLevelConverter.class
)
protected LogHelper.LogLevelEnum logLevel = LogHelper.LogLevelEnum.PROGRESS;

@Parameter(names = { "--version" }, description = "print jadx version")
protected boolean printVersion = false;

Expand Down Expand Up @@ -158,15 +162,7 @@ private boolean process(JCommanderWrapper<JadxCLIArgs> jcw) {
if (threadsCount <= 0) {
throw new JadxException("Threads count must be positive, got: " + threadsCount);
}
if (verbose) {
ch.qos.logback.classic.Logger rootLogger =
(ch.qos.logback.classic.Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
// remove INFO ThresholdFilter
Appender<ILoggingEvent> appender = rootLogger.getAppender("STDOUT");
if (appender != null) {
appender.clearAllFilters();
}
}
LogHelper.setLogLevelFromArgs(this);
} catch (JadxException e) {
System.err.println("ERROR: " + e.getMessage());
jcw.printUsage();
Expand Down Expand Up @@ -339,15 +335,18 @@ public Set<RenameEnum> convert(String value) {
try {
set.add(RenameEnum.valueOf(s.toUpperCase(Locale.ROOT)));
} catch (IllegalArgumentException e) {
String values = Arrays.stream(RenameEnum.values())
.map(v -> '\'' + v.name().toLowerCase(Locale.ROOT) + '\'')
.collect(Collectors.joining(", "));
throw new IllegalArgumentException(
'\'' + s + "' is unknown for parameter " + paramName
+ ", possible values are " + values);
+ ", possible values are " + enumValuesString(RenameEnum.values()));
}
}
return set;
}
}

public static String enumValuesString(Enum<?>[] values) {
return Arrays.stream(values)
.map(v -> '\'' + v.name().toLowerCase(Locale.ROOT) + '\'')
.collect(Collectors.joining(", "));
}
}
93 changes: 93 additions & 0 deletions jadx-cli/src/main/java/jadx/cli/LogHelper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package jadx.cli;

import org.slf4j.LoggerFactory;

import com.beust.jcommander.IStringConverter;

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;

import jadx.api.JadxDecompiler;

public class LogHelper {
private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(LogHelper.class);

public enum LogLevelEnum {
QUIET(Level.OFF),
PROGRESS(Level.OFF),
ERROR(Level.ERROR),
WARN(Level.WARN),
INFO(Level.INFO),
DEBUG(Level.DEBUG);

private final Level level;

LogLevelEnum(Level level) {
this.level = level;
}

public Level getLevel() {
return level;
}
}

public static void setLogLevelFromArgs(JadxCLIArgs args) {
if (isCustomLogConfig()) {
return;
}
LogLevelEnum logLevel = args.logLevel;
if (args.quiet) {
logLevel = LogLevelEnum.QUIET;
} else if (args.verbose) {
logLevel = LogLevelEnum.DEBUG;
}

applyLogLevel(logLevel);
}

public static void applyLogLevel(LogLevelEnum logLevel) {
Logger rootLogger = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
rootLogger.setLevel(logLevel.getLevel());

if (logLevel != LogLevelEnum.QUIET) {
// show progress for all levels except quiet
setLevelForClass(JadxCLI.class, Level.INFO);
setLevelForClass(JadxDecompiler.class, Level.INFO);
}
}

private static void setLevelForClass(Class<?> cls, Level level) {
((Logger) LoggerFactory.getLogger(cls)).setLevel(level);
}

/**
* Try to detect if user provide custom logback config via -Dlogback.configurationFile=
*/
private static boolean isCustomLogConfig() {
try {
String logbackConfig = System.getProperty("logback.configurationFile");
if (logbackConfig == null) {
return false;
}
LOG.debug("Use custom log config: {}", logbackConfig);
return true;
} catch (Exception e) {
LOG.error("Failed to detect custom log config", e);
}
return false;
}

public static class LogLevelConverter implements IStringConverter<LogLevelEnum> {

@Override
public LogLevelEnum convert(String value) {
try {
return LogLevelEnum.valueOf(value.toUpperCase());
} catch (Exception e) {
throw new IllegalArgumentException(
'\'' + value + "' is unknown log level, possible values are "
+ JadxCLIArgs.enumValuesString(LogLevelEnum.values()));
}
}
}
}
5 changes: 1 addition & 4 deletions jadx-cli/src/main/resources/logback.xml
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
<encoder>
<pattern>%-5level - %msg%n</pattern>
</encoder>
</appender>

<root level="DEBUG">
<root level="INFO">
<appender-ref ref="STDOUT"/>
</root>
</configuration>

0 comments on commit bc7a748

Please sign in to comment.