diff --git a/checkstyle.xml b/checkstyle.xml
new file mode 100644
index 0000000..82c2e4d
--- /dev/null
+++ b/checkstyle.xml
@@ -0,0 +1,378 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/java/ghidrust/analyzer/RustStdAnalyzer.java b/src/main/java/ghidrust/analyzer/RustStdAnalyzer.java
index 3e8583d..424d724 100644
--- a/src/main/java/ghidrust/analyzer/RustStdAnalyzer.java
+++ b/src/main/java/ghidrust/analyzer/RustStdAnalyzer.java
@@ -13,34 +13,50 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package ghidrust.analyzer;
-import generic.jar.ResourceFile;
import ghidra.app.services.AbstractAnalyzer;
import ghidra.app.services.AnalysisPriority;
import ghidra.app.services.AnalyzerType;
import ghidra.app.util.importer.MessageLog;
+
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSetView;
import ghidra.program.model.listing.Program;
+
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
+
import ghidra.feature.fid.db.FidFileManager;
import ghidra.framework.Application;
import java.io.IOException;
+import generic.jar.ResourceFile;
+/**
+ * Ghidra analyzer plugin to find whether the program is a Rust binary.
+ */
public class RustStdAnalyzer extends AbstractAnalyzer {
- private static final byte[][] rust_artifacts = {
+ private static final byte[][] rustArtifacts = {
"run with `RUST_BACKTRACE=1` environment variable".getBytes(),
"called `Option::unwrap()` on a `None` value".getBytes(),
"called `Result::unwrap()` on an `Err` value".getBytes()
};
private static final String ENABLED_PROPERTY = "DecompilerParameterAnalyzer.enabled";
+ /**
+ * General plugin initialization.
+ */
public RustStdAnalyzer() {
super("Detect Rust libstd functions",
- "Detects Rust standard library functions from saved signatures and saves analysis time.\n\nProvided by GhidRust",
+ // CHECKSTYLE:OFF
+ """
+ Detects Rust standard library functions from saved signatures and saves analysis time.
+
+ Provided by GhidRust
+ """,
+ // CHECKSTYLE:ON
AnalyzerType.FUNCTION_ANALYZER);
/*
@@ -56,8 +72,8 @@ public class RustStdAnalyzer extends AbstractAnalyzer {
@Override
public boolean getDefaultEnablement(Program program) {
// Make sure the property has not been disabled
- String default_enabled = System.getProperty(ENABLED_PROPERTY);
- if (default_enabled != null && !Boolean.parseBoolean(default_enabled)) {
+ String defaultEnabled = System.getProperty(ENABLED_PROPERTY);
+ if (defaultEnabled != null && !Boolean.parseBoolean(defaultEnabled)) {
return false;
}
@@ -81,15 +97,15 @@ public class RustStdAnalyzer extends AbstractAnalyzer {
return false;
}
- ResourceFile data_dir;
+ ResourceFile dataDir;
try {
- data_dir = Application.getModuleDataSubDirectory("");
+ dataDir = Application.getModuleDataSubDirectory("");
} catch (IOException exc) {
log.appendException(exc);
return false;
}
- ResourceFile[] libs = data_dir.listFiles();
+ ResourceFile[] libs = dataDir.listFiles();
for (ResourceFile lib : libs) {
monitor.checkCanceled();
ffm.addUserFidFile(lib.getFile(true));
@@ -103,7 +119,13 @@ public class RustStdAnalyzer extends AbstractAnalyzer {
super.analysisEnded(program);
}
- /* For exposing the Rust checking code */
+ /**
+ * For exposing the Rust checking code. This can be used as an library call
+ * by any other plugin relying on this plugin.
+ *
+ * @param program The program being analyzed.
+ * @return True if it is a Rust binaru, false otherwise.
+ */
public static boolean isRustBinary(Program program) {
/*
* Taken from
@@ -111,10 +133,12 @@ public class RustStdAnalyzer extends AbstractAnalyzer {
* with-rust.yml
*/
- Address start_search = program.getMinAddress();
- for (byte[] search_string : rust_artifacts) {
- Address found_addr = program.getMemory().findBytes(start_search, search_string, null, true, null);
- if (found_addr != null) {
+ Address startSearch = program.getMinAddress();
+ for (byte[] searchString : rustArtifacts) {
+ Address foundAddr = program.getMemory().findBytes(
+ startSearch, searchString, null, true, null
+ );
+ if (foundAddr != null) {
return true;
}
}
diff --git a/src/main/java/ghidrust/decompiler/RustDecPlugin.java b/src/main/java/ghidrust/decompiler/RustDecPlugin.java
index e7c0fd0..aee579d 100644
--- a/src/main/java/ghidrust/decompiler/RustDecPlugin.java
+++ b/src/main/java/ghidrust/decompiler/RustDecPlugin.java
@@ -13,12 +13,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package ghidrust.decompiler;
+import ghidra.app.events.ProgramActivatedPluginEvent;
+import ghidra.app.events.ProgramClosedPluginEvent;
+import ghidra.app.events.ProgramLocationPluginEvent;
import ghidra.app.plugin.PluginCategoryNames;
-import docking.ActionContext;
+import ghidra.app.DeveloperPluginPackage;
+
import docking.action.DockingAction;
-import ghidra.app.events.*;
+import docking.action.MenuData;
+import docking.ActionContext;
+
import ghidra.framework.plugintool.Plugin;
import ghidra.framework.plugintool.PluginInfo;
import ghidra.framework.plugintool.PluginTool;
@@ -29,39 +36,51 @@ import ghidra.program.model.listing.Program;
import ghidra.program.util.ProgramLocation;
import ghidra.util.Msg;
import ghidrust.analyzer.RustStdAnalyzer;
-import docking.action.MenuData;
-//@formatter:off
+// @formatter:off
+/**
+ * Add the PluginInfo annotation for the Rust decompiler plugin.
+ */
@PluginInfo(
- status = PluginStatus.STABLE,
- packageName = "HELLO",
- category = PluginCategoryNames.ANALYSIS,
- shortDescription = "Rust Decompiler",
- description = "Decompile Rust binaries' assembly to Rust code",
+ status = PluginStatus.STABLE,
+ packageName = DeveloperPluginPackage.NAME,
+ category = PluginCategoryNames.ANALYSIS,
+ shortDescription = "Rust Decompiler",
+ description = "Decompile Rust binaries' assembly to Rust code",
eventsConsumed = {
- ProgramActivatedPluginEvent.class, ProgramLocationPluginEvent.class, ProgramClosedPluginEvent.class
- }
+ ProgramActivatedPluginEvent.class,
+ ProgramLocationPluginEvent.class,
+ ProgramClosedPluginEvent.class
+ }
)
-//@formatter:on
+// @formatter:on
+
public class RustDecPlugin extends Plugin {
Program program;
RustDecProvider provider;
+ /**
+ * Adds docking actions for opening the decompiler and checking whether the
+ * binary is a Rust binary.
+ *
+ * @param tool PluginTool instance responsible for managing RustDecPlugin.
+ */
public RustDecPlugin(PluginTool tool) {
super(tool);
provider = new RustDecProvider(this, getName(), null);
- DockingAction dec_plugin = new DockingAction("GhidRust", getName()) {
+ DockingAction decPlugin = new DockingAction("GhidRust", getName()) {
@Override
public void actionPerformed(ActionContext context) {
- provider.activateProvider();;
+ provider.activateProvider();
+ ;
}
};
- dec_plugin.setEnabled(true);
- dec_plugin.setMenuBarData(new MenuData(new String[] { "GhidRust", "Open decompiler" }));
+ decPlugin.setEnabled(true);
+ decPlugin.setMenuBarData(new MenuData(new String[] { "GhidRust", "Open decompiler" }));
- DockingAction check_plugin = new DockingAction("GhidRust", getName()) {
+ DockingAction checkPlugin = new DockingAction("GhidRust", getName()) {
@Override
public void actionPerformed(ActionContext context) {
if (RustStdAnalyzer.isRustBinary(program)) {
@@ -72,11 +91,13 @@ public class RustDecPlugin extends Plugin {
}
};
- check_plugin.setEnabled(true);
- check_plugin.setMenuBarData(new MenuData(new String[] { "GhidRust", "Check if Rust binary" }));
+ checkPlugin.setEnabled(true);
+ checkPlugin.setMenuBarData(new MenuData(
+ new String[] { "GhidRust", "Check if Rust binary" }
+ ));
- tool.addAction(dec_plugin);
- tool.addAction(check_plugin);
+ tool.addAction(decPlugin);
+ tool.addAction(checkPlugin);
}
@Override
diff --git a/src/main/java/ghidrust/decompiler/RustDecProvider.java b/src/main/java/ghidrust/decompiler/RustDecProvider.java
index 5f00e22..b98b4af 100644
--- a/src/main/java/ghidrust/decompiler/RustDecProvider.java
+++ b/src/main/java/ghidrust/decompiler/RustDecProvider.java
@@ -6,6 +6,8 @@ import ghidra.program.model.listing.Function;
import ghidra.app.decompiler.DecompInterface;
import ghidra.app.decompiler.DecompileResults;
+import ghidrust.decompiler.parser.c.CFormatter;
+import ghidrust.decompiler.parser.c.gen.CParser;
import javax.swing.JComponent;
import javax.swing.JLabel;
@@ -24,26 +26,35 @@ import java.awt.event.ActionEvent;
import docking.ComponentProvider;
import ghidra.util.task.ConsoleTaskMonitor;
import resources.ResourceManager;
-import ghidrust.decompiler.parser.c.CFormatter;
-import ghidrust.decompiler.parser.c.gen.CParser;
+/**
+ * Responsible for decompiling and showing the decompiled code in a window.
+ */
public class RustDecProvider extends ComponentProvider {
private JPanel panel;
- private JTextArea code_area;
- private JLabel func_title;
+ private JTextArea codeArea;
+ private JLabel funcTitle;
private Program prog;
private Address addr;
- private DecompInterface decomp_ifc = null;
+ private DecompInterface decompInterface = null;
private static final String EMPTY_LABEL = "";
+ /**
+ * Initialize the provider by creating a decompilation interface and the
+ * decompilation window.
+ *
+ * @param plugin Calling plugin, which in our case would be RustDecPlugin.
+ * @param owner Owner of the plugin.
+ * @param p Program on which this plugin is being used.
+ */
public RustDecProvider(RustDecPlugin plugin, String owner, Program p) {
super(plugin.getTool(), owner, owner);
setIcon(ResourceManager.loadImage("images/icon.png"));
- decomp_ifc = new DecompInterface();
+ decompInterface = new DecompInterface();
setProgram(p);
buildPanel();
@@ -57,7 +68,7 @@ public class RustDecProvider extends ComponentProvider {
private void buildPanel() {
panel = new JPanel(new BorderLayout());
- func_title = new JLabel(EMPTY_LABEL);
+ funcTitle = new JLabel(EMPTY_LABEL);
JButton reload = new JButton(ResourceManager.loadImage("images/reload.png"));
reload.addActionListener(new ActionListener() {
@@ -68,14 +79,14 @@ public class RustDecProvider extends ComponentProvider {
JToolBar toolbar = new JToolBar("GhidRust", JToolBar.HORIZONTAL);
toolbar.setFloatable(false);
- toolbar.add(func_title);
+ toolbar.add(funcTitle);
toolbar.add(Box.createHorizontalGlue());
toolbar.add(reload);
- code_area = new JTextArea();
- code_area.setEditable(false);
+ codeArea = new JTextArea();
+ codeArea.setEditable(false);
- JScrollPane scroll = new JScrollPane(code_area);
+ JScrollPane scroll = new JScrollPane(codeArea);
scroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
panel.add(toolbar, BorderLayout.PAGE_START);
@@ -86,12 +97,18 @@ public class RustDecProvider extends ComponentProvider {
setVisible(true);
}
+ /**
+ * We save the program in a private class variable to be used later, and
+ * open it using the decompiler interface.
+ *
+ * @param p program to be decompiled.
+ */
public void setProgram(Program p) {
prog = p;
- decomp_ifc.closeProgram();
+ decompInterface.closeProgram();
if (prog != null) {
- decomp_ifc.openProgram(prog);
+ decompInterface.openProgram(prog);
}
}
@@ -99,48 +116,54 @@ public class RustDecProvider extends ComponentProvider {
addr = a;
}
+ /**
+ * When reload is called, we trigger the decompilation.
+ */
public void reload() {
if (prog == null) {
- func_title.setText(EMPTY_LABEL);
- code_area.setText("[?] Open a program to see the decompilation!\n");
+ funcTitle.setText(EMPTY_LABEL);
+ codeArea.setText("[?] Open a program to see the decompilation!\n");
return;
}
if (addr == null) {
- func_title.setText(EMPTY_LABEL);
- code_area.setText("[?] Select a memory location to decompile!\n");
+ funcTitle.setText(EMPTY_LABEL);
+ codeArea.setText("[?] Select a memory location to decompile!\n");
return;
}
Function func = prog.getFunctionManager().getFunctionContaining(addr);
if (func == null) {
- func_title.setText(EMPTY_LABEL);
- code_area.setText("[!] No function found at " + addr.toString() + "\n");
+ funcTitle.setText(EMPTY_LABEL);
+ codeArea.setText("[!] No function found at " + addr.toString() + "\n");
return;
}
- func_title.setText(func.getName());
+ funcTitle.setText(func.getName());
- if (decomp_ifc == null) {
- code_area.setText("[!] Decompiler has not been initialized!\n");
+ if (decompInterface == null) {
+ codeArea.setText("[!] Decompiler has not been initialized!\n");
return;
}
- DecompileResults results = decomp_ifc.decompileFunction(func, 0, new ConsoleTaskMonitor());
- if (results == null || results.getDecompiledFunction() == null || results.getDecompiledFunction().getC() == null) {
- code_area.setText("[!] Failed to decompile " + func.getName() + "\n");
+ DecompileResults results = decompInterface.decompileFunction(
+ func, 0, new ConsoleTaskMonitor()
+ );
+ if (results == null || results.getDecompiledFunction() == null
+ || results.getDecompiledFunction().getC() == null) {
+ codeArea.setText("[!] Failed to decompile " + func.getName() + "\n");
return;
}
String decompiled = results.getDecompiledFunction().getC();
- String rust_code = "";
+ String rustCode = "";
try {
- rust_code = CFormatter.format(CParser.transpile(decompiled));
+ rustCode = CFormatter.format(CParser.transpile(decompiled));
} catch (Exception e) {
- rust_code = "/* [!] Failed to transpile " + func.getName() + " */\n" + decompiled;
+ rustCode = "/* [!] Failed to transpile " + func.getName() + " */\n" + decompiled;
}
- code_area.setText(rust_code);
+ codeArea.setText(rustCode);
}
}
diff --git a/src/main/java/ghidrust/decompiler/parser/Run.java b/src/main/java/ghidrust/decompiler/parser/Run.java
index cae1225..34a7c7c 100644
--- a/src/main/java/ghidrust/decompiler/parser/Run.java
+++ b/src/main/java/ghidrust/decompiler/parser/Run.java
@@ -3,6 +3,9 @@ package ghidrust.decompiler.parser;
import ghidrust.decompiler.parser.c.gen.CParser;
import ghidrust.decompiler.parser.c.CFormatter;
+/**
+ * Run the transpiler as a command line standalone tool (for testing).
+ */
public class Run {
public static void main(String[] args) {
System.out.println(CFormatter.format(CParser.transpile(System.in)));
diff --git a/src/main/java/ghidrust/decompiler/parser/c/CFormatter.java b/src/main/java/ghidrust/decompiler/parser/c/CFormatter.java
index e3c2a91..2be10a3 100644
--- a/src/main/java/ghidrust/decompiler/parser/c/CFormatter.java
+++ b/src/main/java/ghidrust/decompiler/parser/c/CFormatter.java
@@ -1,7 +1,10 @@
package ghidrust.decompiler.parser.c;
+/**
+ * Format decompiled code.
+ */
public class CFormatter {
- static int indent_level;
+ static int indentLevel;
static String indent(int level) {
StringBuffer sb = new StringBuffer("");
@@ -13,38 +16,44 @@ public class CFormatter {
return sb.toString();
}
- public CFormatter(int initial_indent) {
- indent_level = 0;
+ public CFormatter(int initialIndent) {
+ indentLevel = initialIndent;
}
+ /**
+ * Format the code being passed in by adding newlines and semicolons.
+ *
+ * @param code Code as a string.
+ * @return Formatted code.
+ */
public static String format(String code) {
StringBuffer pretty = new StringBuffer("");
int str_len = code.length();
- pretty.append(indent(indent_level));
+ pretty.append(indent(indentLevel));
boolean disable = false;
for (int i = 0; i < str_len; i++) {
if (code.charAt(i) == '{') {
pretty.append("{\n");
- indent_level++;
- pretty.append(indent(indent_level));
+ indentLevel++;
+ pretty.append(indent(indentLevel));
} else if (code.charAt(i) == '}') {
- indent_level--;
+ indentLevel--;
if (code.charAt(i - 1) != ';') {
pretty.append("\n");
- pretty.append(indent(indent_level));
+ pretty.append(indent(indentLevel));
} else {
pretty.deleteCharAt(pretty.length() - 1);
}
pretty.append("}");
if (!(i + 1 < str_len && code.charAt(i + 1) == ' ')) {
pretty.append("\n");
- pretty.append(indent(indent_level));
+ pretty.append(indent(indentLevel));
}
} else if (code.charAt(i) == ';') {
pretty.append(";\n");
- pretty.append(indent(indent_level));
+ pretty.append(indent(indentLevel));
} else if (code.charAt(i) == '@') {
/* special character to denote no action for next char */
i++;
diff --git a/src/main/java/ghidrust/decompiler/parser/c/CVisitor.java b/src/main/java/ghidrust/decompiler/parser/c/CVisitor.java
index 661cca0..4cf8f6d 100644
--- a/src/main/java/ghidrust/decompiler/parser/c/CVisitor.java
+++ b/src/main/java/ghidrust/decompiler/parser/c/CVisitor.java
@@ -1,5 +1,6 @@
package ghidrust.decompiler.parser.c;
+// CHECKSTYLE:OFF
import ghidrust.decompiler.parser.c.gen.*;
import java.util.HashMap;
@@ -453,6 +454,8 @@ public class CVisitor implements CParserVisitor {
return defaultSpacedVisit(node, data, ", ", false);
}
}
+// CHECKSTYLE:ON
+
/*
* JavaCC - OriginalChecksum=fd39d82df2a1b516298b94d6f4a5e997 (do not edit this
* line)
diff --git a/src/main/java/ghidrust/decompiler/parser/c/gen/c.jj b/src/main/java/ghidrust/decompiler/parser/c/gen/c.jj
index 74b636e..797b05e 100644
--- a/src/main/java/ghidrust/decompiler/parser/c/gen/c.jj
+++ b/src/main/java/ghidrust/decompiler/parser/c/gen/c.jj
@@ -1995,4 +1995,4 @@ void Constant() :
}
}
/*@egen*/
-}
\ No newline at end of file
+}