未验证 提交 65086383 编写于 作者: L LBJ-the-GOAT 提交者: GitHub

feat(gui): improve smali printer to show bytecode (#1114) (PR #1126)

* improve smali printer to show bytecode
* set insnStart position before start decoding
* swithed line 62 and line 63, to get the proper bytes, insnStart must to be set before start to decode.

Co-authored-by: tobias <tobias.hotmail.com>
上级 3a69ac23
......@@ -576,6 +576,29 @@ public class ClassNode extends NotificationAttrNode implements ILoadable, ICodeN
sb.append(this.clsData.getDisassembledCode());
}
public String getSmaliV2() {
StringBuilder sb = new StringBuilder();
getSmaliV2(sb);
sb.append(System.lineSeparator());
Set<ClassNode> allInlinedClasses = new LinkedHashSet<>();
getInnerAndInlinedClassesRecursive(allInlinedClasses);
for (ClassNode innerClass : allInlinedClasses) {
innerClass.getSmaliV2(sb);
sb.append(System.lineSeparator());
}
return sb.toString();
}
private void getSmaliV2(StringBuilder sb) {
if (this.clsData == null) {
sb.append(String.format("###### Class %s is created by jadx", getFullName()));
return;
}
sb.append(String.format("###### Class %s (%s)", getFullName(), getRawName()));
sb.append(System.lineSeparator());
sb.append(this.clsData.getDisassembledCodeV2());
}
public ProcessState getState() {
return state;
}
......
......@@ -54,6 +54,7 @@ public class JadxSettings extends JadxCLIArgs {
private boolean checkForUpdates = false;
private List<Path> recentProjects = new ArrayList<>();
private String fontStr = "";
private String smaliFontStr = "";
private String editorThemePath = "";
private LangLocale langLocale = NLS.defaultLocale();
private boolean autoStartJobs = false;
......@@ -68,6 +69,7 @@ public class JadxSettings extends JadxCLIArgs {
private int srhResourceSkipSize = 1000;
private String srhResourceFileExt = ".xml|.html|.js|.json|.txt";
private boolean keepCommonDialogOpen = false;
private boolean smaliAreaShowBytecode = false;
/**
* UI setting: the width of the tree showing the classes, resources, ...
......@@ -377,6 +379,27 @@ public class JadxSettings extends JadxCLIArgs {
}
}
public Font getSmaliFont() {
if (smaliFontStr.isEmpty()) {
return DEFAULT_FONT;
}
try {
return FontUtils.loadByStr(smaliFontStr);
} catch (Exception e) {
LOG.warn("Failed to load font: {} for smali, reset to default", smaliFontStr, e);
setSmaliFont(DEFAULT_FONT);
return DEFAULT_FONT;
}
}
public void setSmaliFont(@Nullable Font font) {
if (font == null) {
this.smaliFontStr = "";
} else {
this.smaliFontStr = FontUtils.convertToStr(font);
}
}
public void setLogLevel(LogHelper.LogLevelEnum level) {
this.logLevel = level;
}
......@@ -430,6 +453,14 @@ public class JadxSettings extends JadxCLIArgs {
return keepCommonDialogOpen;
}
public void setSmaliAreaShowBytecode(boolean yes) {
smaliAreaShowBytecode = yes;
}
public boolean getSmaliAreaShowBytecode() {
return smaliAreaShowBytecode;
}
private void upgradeSettings(int fromVersion) {
LOG.debug("upgrade settings from version: {} to {}", fromVersion, CURRENT_SETTINGS_VERSION);
if (fromVersion == 0) {
......
......@@ -7,8 +7,7 @@ import java.awt.event.ActionEvent;
import java.awt.event.ItemEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Arrays;
import java.util.Collection;
import java.util.*;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
......@@ -292,6 +291,7 @@ public class JadxSettingsWindow extends JDialog {
private SettingsGroup makeEditorGroup() {
JButton fontBtn = new JButton(NLS.str("preferences.select_font"));
JButton smaliFontBtn = new JButton(NLS.str("preferences.select_smali_font"));
EditorTheme[] editorThemes = EditorTheme.getAllThemes();
JComboBox<EditorTheme> themesCbx = new JComboBox<>(editorThemes);
......@@ -311,6 +311,7 @@ public class JadxSettingsWindow extends JDialog {
SettingsGroup group = new SettingsGroup(NLS.str("preferences.editor"));
JLabel fontLabel = group.addRow(getFontLabelStr(), fontBtn);
group.addRow(NLS.str("preferences.theme"), themesCbx);
JLabel smaliFontLabel = group.addRow(getSmaliFontLabelStr(), smaliFontBtn);
fontBtn.addMouseListener(new MouseAdapter() {
@Override
......@@ -327,6 +328,22 @@ public class JadxSettingsWindow extends JDialog {
}
}
});
smaliFontBtn.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
JFontChooser fontChooser = new JPreferredFontChooser();
fontChooser.setSelectedFont(settings.getSmaliFont());
int result = fontChooser.showDialog(JadxSettingsWindow.this);
if (result == JFontChooser.OK_OPTION) {
Font font = fontChooser.getSelectedFont();
LOG.debug("Selected Font: {} for smali", font);
settings.setSmaliFont(font);
mainWindow.loadSettings();
smaliFontLabel.setText(getSmaliFontLabelStr());
}
}
});
return group;
}
......@@ -336,6 +353,12 @@ public class JadxSettingsWindow extends JDialog {
return NLS.str("preferences.font") + ": " + font.getFontName() + ' ' + fontStyleName + ' ' + font.getSize();
}
private String getSmaliFontLabelStr() {
Font font = settings.getSmaliFont();
String fontStyleName = FontUtils.convertFontStyleToString(font.getStyle());
return NLS.str("preferences.smali_font") + ": " + font.getFontName() + ' ' + fontStyleName + ' ' + font.getSize();
}
private SettingsGroup makeDecompilationGroup() {
JCheckBox fallback = new JCheckBox();
fallback.setSelected(settings.isFallbackMode());
......@@ -578,4 +601,42 @@ public class JadxSettingsWindow extends JDialog {
add(Box.createVerticalGlue());
}
}
private static class JPreferredFontChooser extends JFontChooser {
private static final String[] PREFERRED_FONTS = new String[] {
"Monospaced", "Consolas", "Courier", "Courier New",
"Lucida Sans Typewriter", "Lucida Console",
"SimSun", "SimHei",
};
private String[] filteredFonts;
@Override
protected String[] getFontFamilies() {
if (filteredFonts == null) {
GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
Set<String> fontSet = new HashSet<>();
Collections.addAll(fontSet, env.getAvailableFontFamilyNames());
ArrayList<String> found = new ArrayList<>(PREFERRED_FONTS.length);
for (String font : PREFERRED_FONTS) {
if (fontSet.contains(font)) {
found.add(font);
}
}
if (found.size() == PREFERRED_FONTS.length) {
filteredFonts = PREFERRED_FONTS;
} else if (found.size() > 0) {
filteredFonts = new String[found.size()];
for (int i = 0; i < found.size(); i++) {
filteredFonts[i] = found.get(i);
}
} else {
// this machine is crazy.
LOG.warn("Can't found any preferred fonts for smali, use all available.");
filteredFonts = env.getAvailableFontFamilyNames();
}
}
return filteredFonts;
}
}
}
......@@ -107,6 +107,10 @@ public class JClass extends JLoadableNode {
return cls.getSmali();
}
public String getSmaliV2() {
return cls.getClassNode().getSmaliV2();
}
@Override
public String getSyntaxName() {
return SyntaxConstants.SYNTAX_STYLE_JAVA;
......
......@@ -55,9 +55,10 @@ public abstract class AbstractCodeArea extends RSyntaxTextArea {
contentPanel.getTabbedPane().getOpenTabs().values().forEach(v -> {
if (v instanceof AbstractCodeContentPanel) {
AbstractCodeArea codeArea = ((AbstractCodeContentPanel) v).getCodeArea();
codeArea.setLineWrap(wrap);
if (codeArea.isVisible()) {
codeArea.repaint();
setCodeAreaLineWrap(codeArea, wrap);
if (v instanceof ClassCodeContentPanel) {
codeArea = ((ClassCodeContentPanel) v).getSmaliCodeArea();
setCodeAreaLineWrap(codeArea, wrap);
}
}
});
......@@ -116,6 +117,13 @@ public abstract class AbstractCodeArea extends RSyntaxTextArea {
});
}
private void setCodeAreaLineWrap(AbstractCodeArea codeArea, boolean wrap) {
codeArea.setLineWrap(wrap);
if (codeArea.isVisible()) {
codeArea.repaint();
}
}
private String highlightCaretWord(String lastText, int pos) {
String text = getWordByPosition(pos);
if (StringUtils.isEmpty(text)) {
......
package jadx.gui.ui.codearea;
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
import java.awt.*;
import java.awt.event.ActionEvent;
import javax.swing.*;
import org.fife.ui.rsyntaxtextarea.*;
import jadx.gui.settings.JadxSettings;
import jadx.gui.treemodel.JClass;
import jadx.gui.treemodel.JNode;
import jadx.gui.treemodel.TextNode;
import jadx.gui.ui.ContentPanel;
import jadx.gui.utils.NLS;
public final class SmaliArea extends AbstractCodeArea {
private static final long serialVersionUID = 1334485631870306494L;
private final JNode textNode;
private SmaliV2Style smaliV2Style;
private boolean curVersion = false;
private final JCheckBoxMenuItem cbUseSmaliV2;
SmaliArea(ContentPanel contentPanel) {
super(contentPanel);
this.textNode = new TextNode(node.getName());
setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA);
cbUseSmaliV2 = new JCheckBoxMenuItem(NLS.str("popup.bytecode_col"), shouldUseSmaliPrinterV2());
cbUseSmaliV2.setAction(new AbstractAction(NLS.str("popup.bytecode_col")) {
@Override
public void actionPerformed(ActionEvent e) {
boolean usingV2 = shouldUseSmaliPrinterV2();
JadxSettings settings = getContentPanel().getTabbedPane().getMainWindow().getSettings();
settings.setSmaliAreaShowBytecode(!usingV2);
contentPanel.getTabbedPane().getOpenTabs().values().forEach(v -> {
if (v instanceof ClassCodeContentPanel) {
((ClassCodeContentPanel) v).getSmaliCodeArea().refresh();
}
});
settings.sync();
}
});
getPopupMenu().add(cbUseSmaliV2);
if (shouldUseSmaliPrinterV2()) {
loadV2Style();
}
}
@Override
public Font getFont() {
if (smaliV2Style != null && shouldUseSmaliPrinterV2()) {
return smaliV2Style.getFont();
}
return super.getFont();
}
@Override
public Font getFontForTokenType(int type) {
if (shouldUseSmaliPrinterV2()) {
return smaliV2Style.getFont();
}
return super.getFontForTokenType(type);
}
private boolean shouldUseSmaliPrinterV2() {
return getContentPanel().getTabbedPane().getMainWindow().getSettings().getSmaliAreaShowBytecode();
}
private void loadV2Style() {
if (smaliV2Style == null) {
smaliV2Style = new SmaliV2Style(this);
addPropertyChangeListener(SYNTAX_SCHEME_PROPERTY, evt -> {
if (smaliV2Style.refreshTheme() && shouldUseSmaliPrinterV2()) {
setSyntaxScheme(smaliV2Style);
}
});
}
setSyntaxScheme(smaliV2Style);
}
@Override
public void load() {
if (getText().isEmpty()) {
setText(node.getSmali());
boolean useSmaliV2 = shouldUseSmaliPrinterV2();
if (useSmaliV2 != cbUseSmaliV2.getState()) {
cbUseSmaliV2.setState(useSmaliV2);
}
if (getText().isEmpty() || curVersion != useSmaliV2) {
curVersion = useSmaliV2;
if (!useSmaliV2) {
if (getSyntaxScheme() == smaliV2Style) {
Theme theme = getContentPanel().getTabbedPane().getMainWindow().getEditorTheme();
setSyntaxScheme(theme.scheme);
}
setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA);
setText(node.getSmali());
} else {
loadV2Style();
setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_ASSEMBLER_6502);
setText(((JClass) node).getSmaliV2());
}
setCaretPosition(0);
}
}
......@@ -35,4 +115,57 @@ public final class SmaliArea extends AbstractCodeArea {
// this area contains only smali without other node attributes
return textNode;
}
private static class SmaliV2Style extends SyntaxScheme {
SmaliArea smaliArea;
Theme curTheme;
public SmaliV2Style(SmaliArea smaliArea) {
super(true);
this.smaliArea = smaliArea;
curTheme = smaliArea.getContentPanel().getTabbedPane().getMainWindow().getEditorTheme();
updateTheme();
}
public Font getFont() {
return smaliArea.getContentPanel().getTabbedPane().getMainWindow().getSettings().getSmaliFont();
}
public boolean refreshTheme() {
Theme theme = smaliArea.getContentPanel().getTabbedPane().getMainWindow().getEditorTheme();
boolean refresh = theme != curTheme;
if (refresh) {
curTheme = theme;
updateTheme();
}
return refresh;
}
private void updateTheme() {
Style[] mainStyles = curTheme.scheme.getStyles();
Style[] styles = new Style[mainStyles.length];
for (int i = 0; i < mainStyles.length; i++) {
Style mainStyle = mainStyles[i];
if (mainStyle == null) {
styles[i] = new Style();
} else {
// font will be hijacked by getFont & getFontForTokenType,
// so it doesn't need to be set here.
styles[i] = new Style(mainStyle.foreground, mainStyle.background, null);
}
}
setStyles(styles);
}
@Override
public void restoreDefaults(Font baseFont) {
restoreDefaults(baseFont, true);
}
@Override
public void restoreDefaults(Font baseFont, boolean fontStyles) {
// Note: it's a hook for continue using the editor theme, better don't remove it.
}
}
}
......@@ -115,9 +115,11 @@ preferences.excludedPackages.editDialog=<html>Liste der durch Leerzeichen getren
preferences.cfg=Methoden generieren CFG-Grafiken (im 'Punkt'-Format)
preferences.raw_cfg=RAW CFG-Grafiken generieren
preferences.font=Schrift ändern
#preferences.smali_font=
preferences.theme=Thema ändern
preferences.start_jobs=Autom. Hintergrunddekompilierung starten
preferences.select_font=Ändern
#preferences.select_smali_font=
preferences.deobfuscation_on=Deobfuscation aktivieren
preferences.deobfuscation_force=Deobfuscationskartendatei umschreiben erzwingen
preferences.deobfuscation_min_len=Minimale Namenlänge
......@@ -154,6 +156,7 @@ msg.cmd_select_class_error=Klasse\n%s auswählen nicht möglich\nSie existiert n
#msg.rename_node_disabled=
#msg.rename_node_failed=
#popup.bytecode_col=
#popup.line_wrap=
popup.undo=Rückgängig
popup.redo=Wiederholen
......
......@@ -115,9 +115,11 @@ preferences.excludedPackages.editDialog=<html>List of space separated package na
preferences.cfg=Generate methods CFG graphs (in 'dot' format)
preferences.raw_cfg=Generate RAW CFG graphs
preferences.font=Editor font
preferences.smali_font=Smali Editor font
preferences.theme=Editor theme
preferences.start_jobs=Auto start background decompilation
preferences.select_font=Change
preferences.select_smali_font=Change
preferences.deobfuscation_on=Enable deobfuscation
preferences.deobfuscation_force=Force rewrite deobfuscation map file
preferences.deobfuscation_min_len=Minimum name length
......@@ -154,6 +156,7 @@ msg.cmd_select_class_error=Failed to select the class\n%s\nThe class does not ex
msg.rename_node_disabled=Can't rename this node
msg.rename_node_failed=Can't rename %s
popup.bytecode_col=Show Bytecode
popup.line_wrap=Line Wrap
popup.undo=Undo
popup.redo=Redo
......
......@@ -115,9 +115,11 @@ preferences.threads=Número de hilos a procesar
preferences.cfg=Generar methods CFG graphs (in 'dot' format)
preferences.raw_cfg=Generate RAW CFG graphs
preferences.font=Fuente del editor
#preferences.smali_font=
preferences.theme=Tema del editor
preferences.start_jobs=Inicio autom. descompilación de fondo
preferences.select_font=Seleccionar
#preferences.select_smali_font=
preferences.deobfuscation_on=Activar desobfuscación
preferences.deobfuscation_force=Forzar reescritura del fichero de ofuscación
preferences.deobfuscation_min_len=Longitud mínima del nombre
......@@ -154,6 +156,7 @@ msg.index_not_initialized=Índice no inicializado, ¡la bósqueda se desactivar
#msg.rename_node_disabled=
#msg.rename_node_failed=
#popup.bytecode_col=
#popup.line_wrap=
popup.undo=Deshacer
popup.redo=Rehacer
......
......@@ -115,9 +115,11 @@ preferences.excludedPackages.editDialog=<html>RAM 절약을 위해 디컴파일
preferences.cfg=메소드 CFG 그래프 생성 ('dot' 포맷)
preferences.raw_cfg=RAW CFG 그래프 생성
preferences.font=에디터 글씨체
#preferences.smali_font=
preferences.theme=에디터 테마
preferences.start_jobs=백그라운드에서 디컴파일 자동 시작
preferences.select_font=변경
#preferences.select_smali_font=
preferences.deobfuscation_on=난독 해제 활성화
preferences.deobfuscation_force=난독 해제 맵 파일 다시 쓰기
preferences.deobfuscation_min_len=최소 이름 길이
......@@ -154,6 +156,7 @@ msg.cmd_select_class_error=클래스를 선택하지 못했습니다.\n%s\n클
msg.rename_node_disabled=이 노드의 이름을 바꿀 수 없습니다.
msg.rename_node_failed=%s의 이름을 바꿀 수 없습니다.
#popup.bytecode_col=
popup.line_wrap=줄 바꿈
popup.undo=실행 취소
popup.redo=다시 실행
......
......@@ -115,9 +115,11 @@ preferences.excludedPackages.editDialog=<html>将不被解压或索引的以空
preferences.cfg=生成方法的 CFG 图(以 .dot 格式保存)
preferences.raw_cfg=生成原始的 CFG 图
preferences.font=编辑器字体
#preferences.smali_font=
preferences.theme=编辑器主题
preferences.start_jobs=自动进行后台反编译
preferences.select_font=更改
#preferences.select_smali_font=
preferences.deobfuscation_on=启用反混淆
preferences.deobfuscation_force=强制覆盖反混淆映射文件
preferences.deobfuscation_min_len=最小命名长度
......@@ -154,6 +156,7 @@ msg.cmd_select_class_error=无法选择类\n%s\n该类不存在。
#msg.rename_node_disabled=
#msg.rename_node_failed=
#popup.bytecode_col=
#popup.line_wrap=
popup.undo=撤销
popup.redo=重做
......
......@@ -2,9 +2,7 @@ package jadx.plugins.input.dex.insns;
import org.jetbrains.annotations.Nullable;
import jadx.api.plugins.input.data.ICallSite;
import jadx.api.plugins.input.data.IFieldData;
import jadx.api.plugins.input.data.IMethodRef;
import jadx.api.plugins.input.data.*;
import jadx.api.plugins.input.insns.InsnData;
import jadx.api.plugins.input.insns.InsnIndexType;
import jadx.api.plugins.input.insns.Opcode;
......@@ -21,6 +19,7 @@ public class DexInsnData implements InsnData {
private boolean decoded;
private int opcodeUnit;
private int length;
private int insnStart;
private int offset;
private int[] argsReg = new int[5];
......@@ -49,6 +48,11 @@ public class DexInsnData implements InsnData {
return offset;
}
@Override
public int getFileOffset() {
return insnStart;
}
@Override
public Opcode getOpcode() {
DexInsnInfo info = this.insnInfo;
......@@ -58,6 +62,11 @@ public class DexInsnData implements InsnData {
return info.getApiOpcode();
}
@Override
public byte[] getByteCode() {
return externalReader.getByteCode(insnStart, length * 2); // a unit is 2 bytes
}
@Override
public int getRawOpcodeUnit() {
return opcodeUnit;
......@@ -118,6 +127,20 @@ public class DexInsnData implements InsnData {
return externalReader.getCallSite(index, secondExtReader);
}
/**
* Currently, protoIndex is either being stored at index or target, index for const-method-type,
* target for invoke-polymorphic(/range)
*/
@Override
public IMethodProto getIndexAsProto(int protoIndex) {
return externalReader.getMethodProto(protoIndex);
}
@Override
public IMethodHandle getIndexAsMethodHandle() {
return externalReader.getMethodHandle(index);
}
@Nullable
@Override
public ICustomPayload getPayload() {
......@@ -144,6 +167,10 @@ public class DexInsnData implements InsnData {
this.length = length;
}
public void setInsnStart(int start) {
this.insnStart = start;
}
public void setLiteral(long literal) {
this.literal = literal;
}
......
......@@ -230,4 +230,60 @@ public class DexOpcodes {
public static final int PACKED_SWITCH_PAYLOAD = 0x0100;
public static final int SPARSE_SWITCH_PAYLOAD = 0x0200;
public static final int FILL_ARRAY_DATA_PAYLOAD = 0x0300;
public static final String MNE_UNUSED = "(unused)";
public static final String[] MNEMONICS = new String[] {
"nop", "move", "move/from16", "move/16", "move-wide",
"move-wide/from16", "move-wide/16", "move-object", "move-object/from16", "move-object/16",
"move-result", "move-result-wide", "move-result-object", "move-exception", "return-void",
"return", "return-wide", "return-object", "const/4", "const/16",
"const", "const/high16", "const-wide/16", "const-wide/32", "const-wide",
"const-wide/high16", "const-string", "const-string/jumbo", "const-class", "monitor-enter",
"monitor-exit", "check-cast", "instance-of", "array-length", "new-instance",
"new-array", "filled-new-array", "filled-new-array/range", "fill-array-data", "throw",
"goto", "goto/16", "goto/32", "packed-switch", "sparse-switch",
"cmpl-float", "cmpg-float", "cmpl-double", "cmpg-double", "cmp-long",
"if-eq", "if-ne", "if-lt", "if-ge", "if-gt",
"if-le", "if-eqz", "if-nez", "if-ltz", "if-gez",
"if-gtz", "if-lez", "(unused)", "(unused)", "(unused)",
"(unused)", "(unused)", "(unused)", "aget", "aget-wide",
"aget-object", "aget-boolean", "aget-byte", "aget-char", "aget-short",
"aput", "aput-wide", "aput-object", "aput-boolean", "aput-byte",
"aput-char", "aput-short", "iget", "iget-wide", "iget-object",
"iget-boolean", "iget-byte", "iget-char", "iget-short", "iput",
"iput-wide", "iput-object", "iput-boolean", "iput-byte", "iput-char",
"iput-short", "sget", "sget-wide", "sget-object", "sget-boolean",
"sget-byte", "sget-char", "sget-short", "sput", "sput-wide",
"sput-object", "sput-boolean", "sput-byte", "sput-char", "sput-short",
"invoke-virtual", "invoke-super", "invoke-direct", "invoke-static", "invoke-interface",
"(unused)", "invoke-virtual/range", "invoke-super/range", "invoke-direct/range", "invoke-static/range",
"invoke-interface/range", "(unused)", "(unused)", "neg-int", "not-int",
"neg-long", "not-long", "neg-float", "neg-double", "int-to-long",
"int-to-float", "int-to-double", "long-to-int", "long-to-float", "long-to-double",
"float-to-int", "float-to-long", "float-to-double", "double-to-int", "double-to-long",
"double-to-float", "int-to-byte", "int-to-char", "int-to-short", "add-int",
"sub-int", "mul-int", "div-int", "rem-int", "and-int",
"or-int", "xor-int", "shl-int", "shr-int", "ushr-int",
"add-long", "sub-long", "mul-long", "div-long", "rem-long",
"and-long", "or-long", "xor-long", "shl-long", "shr-long",
"ushr-long", "add-float", "sub-float", "mul-float", "div-float",
"rem-float", "add-double", "sub-double", "mul-double", "div-double",
"rem-double", "add-int/2addr", "sub-int/2addr", "mul-int/2addr", "div-int/2addr",
"rem-int/2addr", "and-int/2addr", "or-int/2addr", "xor-int/2addr", "shl-int/2addr",
"shr-int/2addr", "ushr-int/2addr", "add-long/2addr", "sub-long/2addr", "mul-long/2addr",
"div-long/2addr", "rem-long/2addr", "and-long/2addr", "or-long/2addr", "xor-long/2addr",
"shl-long/2addr", "shr-long/2addr", "ushr-long/2addr", "add-float/2addr", "sub-float/2addr",
"mul-float/2addr", "div-float/2addr", "rem-float/2addr", "add-double/2addr", "sub-double/2addr",
"mul-double/2addr", "div-double/2addr", "rem-double/2addr", "add-int/lit16", "rsub-int",
"mul-int/lit16", "div-int/lit16", "rem-int/lit16", "and-int/lit16", "or-int/lit16",
"xor-int/lit16", "add-int/lit8", "rsub-int/lit8", "mul-int/lit8", "div-int/lit8",
"rem-int/lit8", "and-int/lit8", "or-int/lit8", "xor-int/lit8", "shl-int/lit8",
"shr-int/lit8", "ushr-int/lit8", "(unused)", "(unused)", "(unused)",
"(unused)", "(unused)", "(unused)", "(unused)", "(unused)",
"(unused)", "(unused)", "(unused)", "(unused)", "(unused)",
"(unused)", "(unused)", "(unused)", "(unused)", "(unused)",
"(unused)", "(unused)", "(unused)", "(unused)", "(unused)",
"invoke-polymorphic", "invoke-polymorphic/range", "invoke-custom", "invoke-custom/range", "const-method-handle",
"const-method-type" };
}
......@@ -13,6 +13,7 @@ import jadx.api.plugins.input.data.IMethodData;
import jadx.api.plugins.input.data.annotations.EncodedValue;
import jadx.api.plugins.input.data.annotations.IAnnotation;
import jadx.plugins.input.dex.sections.annotations.AnnotationsParser;
import jadx.plugins.input.dex.smali.SmaliPrinter;
import jadx.plugins.input.dex.utils.SmaliUtils;
public class DexClassData implements IClassData {
......@@ -193,6 +194,11 @@ public class DexClassData implements IClassData {
return SmaliUtils.getSmaliCode(dexBuf, getClassDefOffset());
}
@Override
public String getDisassembledCodeV2() {
return SmaliPrinter.printClass(this);
}
@Override
public String toString() {
return getType();
......
......@@ -59,8 +59,10 @@ public class DexCodeReader implements ICodeReader {
int size = in.readInt();
int offset = 0; // in code units (2 byte)
while (offset < size) {
int insnStart = in.getAbsPos();
int opcodeUnit = in.readUShort();
DexInsnInfo insnInfo = DexInsnInfo.get(opcodeUnit);
insnData.setInsnStart(insnStart);
insnData.setOffset(offset);
insnData.setInsnInfo(insnInfo);
insnData.setOpcodeUnit(opcodeUnit);
......
......@@ -45,6 +45,14 @@ public class SectionReader {
return new SectionReader(this, off);
}
public byte[] getByteCode(int start, int len) {
int pos = buf.position();
buf.position(start);
byte[] bytes = readByteArray(len);
buf.position(pos);
return bytes;
}
private static ByteBuffer duplicate(ByteBuffer baseBuffer, int off) {
ByteBuffer dupBuf = baseBuffer.duplicate();
dupBuf.order(ByteOrder.LITTLE_ENDIAN);
......
......@@ -31,4 +31,6 @@ public interface IClassData {
List<IAnnotation> getAnnotations();
String getDisassembledCode();
String getDisassembledCodeV2();
}
......@@ -34,4 +34,9 @@ public class FieldRefHandle implements IMethodHandle {
public void load() {
// already loaded
}
@Override
public String toString() {
return type + ": " + fieldRef;
}
}
......@@ -2,19 +2,21 @@ package jadx.api.plugins.input.insns;
import org.jetbrains.annotations.Nullable;
import jadx.api.plugins.input.data.ICallSite;
import jadx.api.plugins.input.data.IFieldData;
import jadx.api.plugins.input.data.IMethodRef;
import jadx.api.plugins.input.data.*;
import jadx.api.plugins.input.insns.custom.ICustomPayload;
public interface InsnData {
void decode();
int getOffset();
int getOffset(); // offset within method
int getFileOffset(); // offset within dex file
Opcode getOpcode();
byte[] getByteCode();
InsnIndexType getIndexType();
int getRawOpcodeUnit();
......@@ -39,6 +41,10 @@ public interface InsnData {
ICallSite getIndexAsCallSite();
IMethodProto getIndexAsProto(int protoIndex);
IMethodHandle getIndexAsMethodHandle();
@Nullable
ICustomPayload getPayload();
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册