fix(smali-input): improve error report for smali assemble (#2411)
This commit is contained in:
+8
-15
@@ -1,11 +1,8 @@
|
||||
package jadx.plugins.input.smali;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.io.Reader;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.PathMatcher;
|
||||
import java.util.ArrayList;
|
||||
@@ -33,12 +30,8 @@ public class SmaliConvert {
|
||||
if (smaliFiles.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
|
||||
collectSystemErrors(out, () -> compile(smaliFiles, options));
|
||||
boolean success = out.size() == 0;
|
||||
if (!success) {
|
||||
LOG.error("Smali error:\n{}", out);
|
||||
}
|
||||
try {
|
||||
compile(smaliFiles, options);
|
||||
} catch (Exception e) {
|
||||
LOG.error("Smali process error", e);
|
||||
}
|
||||
@@ -56,7 +49,7 @@ public class SmaliConvert {
|
||||
int threads = options.getThreads();
|
||||
LOG.debug("Compiling smali files: {}, threads: {}", inputFiles.size(), threads);
|
||||
long start = System.currentTimeMillis();
|
||||
if (threads == 1) {
|
||||
if (threads == 1 || inputFiles.size() == 1) {
|
||||
for (Path inputFile : inputFiles) {
|
||||
assemble(inputFile, smaliOptions);
|
||||
}
|
||||
@@ -78,12 +71,12 @@ public class SmaliConvert {
|
||||
}
|
||||
|
||||
private void assemble(Path inputFile, SmaliOptions smaliOptions) {
|
||||
String fileName = inputFile.toAbsolutePath().toString();
|
||||
try (Reader reader = Files.newBufferedReader(inputFile)) {
|
||||
byte[] assemble = SmaliUtils.assemble(reader, smaliOptions);
|
||||
dexData.add(new SimpleDexData(fileName, assemble));
|
||||
Path path = inputFile.toAbsolutePath();
|
||||
try {
|
||||
byte[] dexContent = SmaliUtils.assemble(path.toFile(), smaliOptions);
|
||||
dexData.add(new SimpleDexData(path.toString(), dexContent));
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Fail to compile: " + fileName, e);
|
||||
LOG.error("Failed to assemble smali file: {}", path, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+66
-27
@@ -1,17 +1,20 @@
|
||||
package jadx.plugins.input.smali;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.antlr.runtime.CommonTokenStream;
|
||||
import org.antlr.runtime.RecognitionException;
|
||||
import org.antlr.runtime.TokenSource;
|
||||
import org.antlr.runtime.TokenStream;
|
||||
import org.antlr.runtime.tree.CommonTreeNodeStream;
|
||||
import org.antlr.runtime.tree.TreeNodeStream;
|
||||
|
||||
import com.android.tools.smali.dexlib2.Opcodes;
|
||||
import com.android.tools.smali.dexlib2.writer.builder.DexBuilder;
|
||||
import com.android.tools.smali.dexlib2.writer.io.MemoryDataStore;
|
||||
import com.android.tools.smali.smali.LexerErrorInterface;
|
||||
import com.android.tools.smali.smali.SmaliOptions;
|
||||
import com.android.tools.smali.smali.smaliFlexLexer;
|
||||
import com.android.tools.smali.smali.smaliParser;
|
||||
@@ -24,31 +27,67 @@ import com.android.tools.smali.smali.smaliTreeWalker;
|
||||
public class SmaliUtils {
|
||||
|
||||
@SuppressWarnings("ExtractMethodRecommender")
|
||||
public static byte[] assemble(Reader reader, SmaliOptions options) throws IOException, RecognitionException {
|
||||
LexerErrorInterface lexer = new smaliFlexLexer(reader, options.apiLevel);
|
||||
CommonTokenStream tokens = new CommonTokenStream((TokenSource) lexer);
|
||||
smaliParser parser = new smaliParser(tokens);
|
||||
parser.setVerboseErrors(options.verboseErrors);
|
||||
parser.setAllowOdex(options.allowOdexOpcodes);
|
||||
parser.setApiLevel(options.apiLevel);
|
||||
smaliParser.smali_file_return parseResult = parser.smali_file();
|
||||
if (parser.getNumberOfSyntaxErrors() > 0 || lexer.getNumberOfSyntaxErrors() > 0) {
|
||||
throw new RuntimeException("Parse error");
|
||||
}
|
||||
CommonTreeNodeStream treeStream = new CommonTreeNodeStream(parseResult.getTree());
|
||||
treeStream.setTokenStream(tokens);
|
||||
public static byte[] assemble(File smaliFile, SmaliOptions options) throws IOException {
|
||||
StringBuilder errors = new StringBuilder();
|
||||
try (FileInputStream fis = new FileInputStream(smaliFile);
|
||||
InputStreamReader reader = new InputStreamReader(fis, StandardCharsets.UTF_8)) {
|
||||
|
||||
DexBuilder dexBuilder = new DexBuilder(Opcodes.forApi(options.apiLevel));
|
||||
smaliTreeWalker dexGen = new smaliTreeWalker(treeStream);
|
||||
dexGen.setApiLevel(options.apiLevel);
|
||||
dexGen.setVerboseErrors(options.verboseErrors);
|
||||
dexGen.setDexBuilder(dexBuilder);
|
||||
dexGen.smali_file();
|
||||
if (dexGen.getNumberOfSyntaxErrors() > 0) {
|
||||
throw new RuntimeException("Compile error");
|
||||
smaliFlexLexer lexer = new smaliFlexLexer(reader, options.apiLevel);
|
||||
lexer.setSourceFile(smaliFile);
|
||||
CommonTokenStream tokens = new CommonTokenStream(lexer);
|
||||
ParserWrapper parser = new ParserWrapper(tokens, errors);
|
||||
parser.setVerboseErrors(options.verboseErrors);
|
||||
parser.setAllowOdex(options.allowOdexOpcodes);
|
||||
parser.setApiLevel(options.apiLevel);
|
||||
ParserWrapper.smali_file_return parseResult = parser.smali_file();
|
||||
if (parser.getNumberOfSyntaxErrors() > 0 || lexer.getNumberOfSyntaxErrors() > 0) {
|
||||
throw new RuntimeException("Smali parse error: " + errors);
|
||||
}
|
||||
CommonTreeNodeStream treeStream = new CommonTreeNodeStream(parseResult.getTree());
|
||||
treeStream.setTokenStream(tokens);
|
||||
|
||||
DexBuilder dexBuilder = new DexBuilder(Opcodes.forApi(options.apiLevel));
|
||||
TreeWalkerWrapper dexGen = new TreeWalkerWrapper(treeStream, errors);
|
||||
dexGen.setApiLevel(options.apiLevel);
|
||||
dexGen.setVerboseErrors(options.verboseErrors);
|
||||
dexGen.setDexBuilder(dexBuilder);
|
||||
dexGen.smali_file();
|
||||
if (dexGen.getNumberOfSyntaxErrors() > 0) {
|
||||
throw new RuntimeException("Smali compile error: " + errors);
|
||||
}
|
||||
MemoryDataStore dataStore = new MemoryDataStore();
|
||||
dexBuilder.writeTo(dataStore);
|
||||
return dataStore.getData();
|
||||
} catch (RecognitionException e) {
|
||||
throw new RuntimeException("Smali process error: " + errors, e);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class ParserWrapper extends smaliParser {
|
||||
private final StringBuilder errors;
|
||||
|
||||
public ParserWrapper(TokenStream input, StringBuilder errors) {
|
||||
super(input);
|
||||
this.errors = errors;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emitErrorMessage(String msg) {
|
||||
errors.append('\n').append(msg);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class TreeWalkerWrapper extends smaliTreeWalker {
|
||||
private final StringBuilder errors;
|
||||
|
||||
public TreeWalkerWrapper(TreeNodeStream input, StringBuilder errors) {
|
||||
super(input);
|
||||
this.errors = errors;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emitErrorMessage(String msg) {
|
||||
errors.append('\n').append(msg);
|
||||
}
|
||||
MemoryDataStore dataStore = new MemoryDataStore();
|
||||
dexBuilder.writeTo(dataStore);
|
||||
return dataStore.getData();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user