Make the decompiler plugin invoke the transpiler

This commit is contained in:
Dhruv Maroo
2023-04-22 07:04:44 +05:30
parent 8f916a6a8d
commit 59fef18c3a
9 changed files with 1511 additions and 1454 deletions

View File

@@ -22,9 +22,12 @@ import java.awt.event.ActionListener;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import docking.ComponentProvider; import docking.ComponentProvider;
import ghidra.util.Msg;
import ghidra.util.task.ConsoleTaskMonitor; import ghidra.util.task.ConsoleTaskMonitor;
import resources.ResourceManager; import resources.ResourceManager;
import ghidrust.decompiler.parser.c.gen.CParser;
public class RustDecProvider extends ComponentProvider { public class RustDecProvider extends ComponentProvider {
private JPanel panel; private JPanel panel;
private JTextArea code_area; private JTextArea code_area;
@@ -34,6 +37,7 @@ public class RustDecProvider extends ComponentProvider {
private Address addr; private Address addr;
private DecompInterface decomp_ifc = null; private DecompInterface decomp_ifc = null;
private CParser transpiler = null;
private static final String EMPTY_LABEL = "<none>"; private static final String EMPTY_LABEL = "<none>";
@@ -125,11 +129,20 @@ public class RustDecProvider extends ComponentProvider {
} }
DecompileResults results = decomp_ifc.decompileFunction(func, 0, new ConsoleTaskMonitor()); DecompileResults results = decomp_ifc.decompileFunction(func, 0, new ConsoleTaskMonitor());
if (results == null || results.getDecompiledFunction() == null) { if (results == null || results.getDecompiledFunction() == null || results.getDecompiledFunction().getC() == null) {
code_area.setText("[!] Failed to decompile " + func.getName() + "\n"); code_area.setText("[!] Failed to decompile " + func.getName() + "\n");
return; return;
} }
code_area.setText(results.getDecompiledFunction().getC()); String decompiled = results.getDecompiledFunction().getC();
String rust_code = "";
try {
rust_code = CParser.transpile(decompiled);
} catch (Exception e) {
rust_code = "/* [!] Failed to transpile " + func.getName() + " */\n" + decompiled;
}
code_area.setText(rust_code);
} }
} }

View File

@@ -4,6 +4,6 @@ import ghidrust.decompiler.parser.c.gen.CParser;
public class Run { public class Run {
public static void main(String[] args) { public static void main(String[] args) {
System.out.println(CParser.transpile("int main(int a) { int c = 2; return 0; }")); System.out.println(CParser.transpile("/* hello::return_0 */\n\n undefined8 hello::return_0(void)\n\n {\n return 0;\n }"));
} }
} }

View File

@@ -98,7 +98,24 @@ public class CVisitor implements CParserVisitor {
} }
public Object visit(ASTDeclaration node, Object data) { public Object visit(ASTDeclaration node, Object data) {
return defaultVisit(node, data); StringBuilder sb = new StringBuilder("");
String[] ret = (String[]) node.jjtGetChild(1).jjtAccept(this, data);
for (int i = 0; i < ret.length / 2; i++) {
for (int j = 0; j < indent_level; j++) {
sb.append("\t");
}
sb.append("let mut ");
sb.append(ret[2 * i]);
sb.append(": ");
sb.append(node.jjtGetChild(0).jjtAccept(this, data));
sb.append(" = ");
sb.append(ret[2 * i + 1]);
sb.append(";\n");
}
return sb.toString();
} }
public Object visit(ASTDeclarationList node, Object data) { public Object visit(ASTDeclarationList node, Object data) {
@@ -106,22 +123,30 @@ public class CVisitor implements CParserVisitor {
} }
public Object visit(ASTDeclarationSpecifiers node, Object data) { public Object visit(ASTDeclarationSpecifiers node, Object data) {
return defaultVisit(node, data); return defaultSpacedVisit(node, data);
} }
public Object visit(ASTInitDeclaratorList node, Object data) { public Object visit(ASTInitDeclaratorList node, Object data) {
if (node.jjtGetNumChildren() == 1) { String[] ret = new String[node.jjtGetNumChildren() * 2];
return node.jjtGetChild(0).jjtAccept(this, data); for (int i = 0; i < node.jjtGetNumChildren(); i++) {
} else { String[] child_ret = (String[]) node.jjtGetChild(i).jjtAccept(this, data);
StringBuilder sb = new StringBuilder("&"); ret[2 * i] = child_ret[0];
sb.append(node.jjtGetChild(0).jjtAccept(this, data)); ret[2 * i + 1] = child_ret[1];
sb.append(node.jjtGetChild(1).jjtAccept(this, data));
return sb.toString();
} }
return ret;
} }
public Object visit(ASTInitDeclarator node, Object data) { public Object visit(ASTInitDeclarator node, Object data) {
return defaultVisit(node, data); String[] ret = new String[2];
ret[0] = (String) node.jjtGetChild(0).jjtAccept(this, data);
if (node.jjtGetNumChildren() == 1) {
ret[1] = "0";
} else {
ret[1] = (String) node.jjtGetChild(1).jjtAccept(this, data);
}
return ret;
} }
public Object visit(ASTSpecifierQualifierList node, Object data) { public Object visit(ASTSpecifierQualifierList node, Object data) {
@@ -175,8 +200,6 @@ public class CVisitor implements CParserVisitor {
public Object visit(ASTParameterDeclaration node, Object data) { public Object visit(ASTParameterDeclaration node, Object data) {
StringBuilder param = new StringBuilder((String) defaultSpacedVisit(node, data)); StringBuilder param = new StringBuilder((String) defaultSpacedVisit(node, data));
/* Get rid of the trailing space */
param.setLength(param.length() - 1);
return param.toString(); return param.toString();
} }
@@ -237,11 +260,9 @@ public class CVisitor implements CParserVisitor {
for (int i = 0; i < indent_level; i++) { for (int i = 0; i < indent_level; i++) {
sb.append("\t"); sb.append("\t");
} }
if (node.jjtGetNumChildren() == 0 || node.jjtGetChild(0) instanceof ASTExpression) { if (node.jjtGetNumChildren() > 0 && node.jjtGetChild(0) instanceof ASTExpression) {
sb.append("return ");
sb.append(node.jjtGetChild(0).jjtAccept(this, data)); sb.append(node.jjtGetChild(0).jjtAccept(this, data));
sb.append(";");
} else { } else {
sb.append(defaultVisit(node, data)); sb.append(defaultVisit(node, data));
} }

File diff suppressed because it is too large Load Diff

View File

@@ -100,6 +100,8 @@ public interface CParserConstants {
int LETTER = 55; int LETTER = 55;
/** RegularExpression Id. */ /** RegularExpression Id. */
int DIGIT = 56; int DIGIT = 56;
/** RegularExpression Id. */
int SEPARATOR = 57;
/** Lexical state. */ /** Lexical state. */
int DEFAULT = 0; int DEFAULT = 0;
@@ -165,6 +167,7 @@ public interface CParserConstants {
"<IDENTIFIER>", "<IDENTIFIER>",
"<LETTER>", "<LETTER>",
"<DIGIT>", "<DIGIT>",
"<SEPARATOR>",
"\";\"", "\";\"",
"\",\"", "\",\"",
"\"=\"", "\"=\"",

View File

@@ -1,7 +1,7 @@
package ghidrust.decompiler.parser.c.gen; package ghidrust.decompiler.parser.c.gen;
/* Generated By:JavaCC: Do not edit this line. SimpleCharStream.java Version 7.0 */ /* Generated By:JavaCC: Do not edit this line. SimpleCharStream.java Version 7.0 */
/* JavaCCOptions:STATIC=true,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */ /* JavaCCOptions:STATIC=false,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
/** /**
* An implementation of interface CharStream, where the stream is assumed to * An implementation of interface CharStream, where the stream is assumed to
* contain only ASCII characters (without unicode processing). * contain only ASCII characters (without unicode processing).
@@ -10,35 +10,35 @@ package ghidrust.decompiler.parser.c.gen;
public class SimpleCharStream public class SimpleCharStream
{ {
/** Whether parser is static. */ /** Whether parser is static. */
public static final boolean staticFlag = true; public static final boolean staticFlag = false;
static int bufsize; int bufsize;
static int available; int available;
static int tokenBegin; int tokenBegin;
/** Position in buffer. */ /** Position in buffer. */
static public int bufpos = -1; public int bufpos = -1;
static protected int bufline[]; protected int bufline[];
static protected int bufcolumn[]; protected int bufcolumn[];
static protected int column = 0; protected int column = 0;
static protected int line = 1; protected int line = 1;
static protected boolean prevCharIsCR = false; protected boolean prevCharIsCR = false;
static protected boolean prevCharIsLF = false; protected boolean prevCharIsLF = false;
static protected java.io.Reader inputStream; protected java.io.Reader inputStream;
static protected char[] buffer; protected char[] buffer;
static protected int maxNextCharInd = 0; protected int maxNextCharInd = 0;
static protected int inBuf = 0; protected int inBuf = 0;
static protected int tabSize = 1; protected int tabSize = 1;
static protected boolean trackLineColumn = true; protected boolean trackLineColumn = true;
static public void setTabSize(int i) { tabSize = i; } public void setTabSize(int i) { tabSize = i; }
static public int getTabSize() { return tabSize; } public int getTabSize() { return tabSize; }
static protected void ExpandBuff(boolean wrapAround) protected void ExpandBuff(boolean wrapAround)
{ {
char[] newbuffer = new char[bufsize + 2048]; char[] newbuffer = new char[bufsize + 2048];
int newbufline[] = new int[bufsize + 2048]; int newbufline[] = new int[bufsize + 2048];
@@ -87,7 +87,7 @@ public class SimpleCharStream
tokenBegin = 0; tokenBegin = 0;
} }
static protected void FillBuff() throws java.io.IOException protected void FillBuff() throws java.io.IOException
{ {
if (maxNextCharInd == available) if (maxNextCharInd == available)
{ {
@@ -132,7 +132,7 @@ public class SimpleCharStream
} }
/** Start. */ /** Start. */
static public char BeginToken() throws java.io.IOException public char BeginToken() throws java.io.IOException
{ {
tokenBegin = -1; tokenBegin = -1;
char c = readChar(); char c = readChar();
@@ -141,7 +141,7 @@ public class SimpleCharStream
return c; return c;
} }
static protected void UpdateLineColumn(char c) protected void UpdateLineColumn(char c)
{ {
column++; column++;
@@ -182,7 +182,7 @@ public class SimpleCharStream
} }
/** Read a character. */ /** Read a character. */
static public char readChar() throws java.io.IOException public char readChar() throws java.io.IOException
{ {
if (inBuf > 0) if (inBuf > 0)
{ {
@@ -209,7 +209,7 @@ public class SimpleCharStream
* @see #getEndColumn * @see #getEndColumn
*/ */
static public int getColumn() { public int getColumn() {
return bufcolumn[bufpos]; return bufcolumn[bufpos];
} }
@@ -219,32 +219,32 @@ public class SimpleCharStream
* @see #getEndLine * @see #getEndLine
*/ */
static public int getLine() { public int getLine() {
return bufline[bufpos]; return bufline[bufpos];
} }
/** Get token end column number. */ /** Get token end column number. */
static public int getEndColumn() { public int getEndColumn() {
return bufcolumn[bufpos]; return bufcolumn[bufpos];
} }
/** Get token end line number. */ /** Get token end line number. */
static public int getEndLine() { public int getEndLine() {
return bufline[bufpos]; return bufline[bufpos];
} }
/** Get token beginning column number. */ /** Get token beginning column number. */
static public int getBeginColumn() { public int getBeginColumn() {
return bufcolumn[tokenBegin]; return bufcolumn[tokenBegin];
} }
/** Get token beginning line number. */ /** Get token beginning line number. */
static public int getBeginLine() { public int getBeginLine() {
return bufline[tokenBegin]; return bufline[tokenBegin];
} }
/** Backup a number of characters. */ /** Backup a number of characters. */
static public void backup(int amount) { public void backup(int amount) {
inBuf += amount; inBuf += amount;
if ((bufpos -= amount) < 0) if ((bufpos -= amount) < 0)
@@ -255,10 +255,6 @@ public class SimpleCharStream
public SimpleCharStream(java.io.Reader dstream, int startline, public SimpleCharStream(java.io.Reader dstream, int startline,
int startcolumn, int buffersize) int startcolumn, int buffersize)
{ {
if (inputStream != null)
throw new Error("\n ERROR: Second call to the constructor of a static SimpleCharStream.\n" +
" You must either use ReInit() or set the JavaCC option STATIC to false\n" +
" during the generation of this class.");
inputStream = dstream; inputStream = dstream;
line = startline; line = startline;
column = startcolumn - 1; column = startcolumn - 1;
@@ -392,7 +388,7 @@ public class SimpleCharStream
ReInit(dstream, startline, startcolumn, 4096); ReInit(dstream, startline, startcolumn, 4096);
} }
/** Get token literal value. */ /** Get token literal value. */
static public String GetImage() public String GetImage()
{ {
if (bufpos >= tokenBegin) if (bufpos >= tokenBegin)
return new String(buffer, tokenBegin, bufpos - tokenBegin + 1); return new String(buffer, tokenBegin, bufpos - tokenBegin + 1);
@@ -402,7 +398,7 @@ public class SimpleCharStream
} }
/** Get the suffix. */ /** Get the suffix. */
static public char[] GetSuffix(int len) public char[] GetSuffix(int len)
{ {
char[] ret = new char[len]; char[] ret = new char[len];
@@ -419,7 +415,7 @@ public class SimpleCharStream
} }
/** Reset buffer when finished. */ /** Reset buffer when finished. */
static public void Done() public void Done()
{ {
buffer = null; buffer = null;
bufline = null; bufline = null;
@@ -429,7 +425,7 @@ public class SimpleCharStream
/** /**
* Method to adjust line and column numbers for the start of a token. * Method to adjust line and column numbers for the start of a token.
*/ */
static public void adjustBeginLineColumn(int newLine, int newCol) public void adjustBeginLineColumn(int newLine, int newCol)
{ {
int start = tokenBegin; int start = tokenBegin;
int len; int len;
@@ -472,7 +468,7 @@ public class SimpleCharStream
line = bufline[j]; line = bufline[j];
column = bufcolumn[j]; column = bufcolumn[j];
} }
static boolean getTrackLineColumn() { return trackLineColumn; } boolean getTrackLineColumn() { return trackLineColumn; }
static void setTrackLineColumn(boolean tlc) { trackLineColumn = tlc; } void setTrackLineColumn(boolean tlc) { trackLineColumn = tlc; }
} }
/* JavaCC - OriginalChecksum=052d2c8783a7a693ccde91d90feb1d3b (do not edit this line) */ /* JavaCC - OriginalChecksum=320e3957affec8972ad656fb86b8d782 (do not edit this line) */

View File

@@ -12,6 +12,7 @@ From: https://github.com/javacc/javacc/blob/master/grammars/CParser.jj
options { options {
STATIC = false;
} }
PARSER_BEGIN(CParser) PARSER_BEGIN(CParser)
@@ -22,7 +23,7 @@ import java.nio.charset.StandardCharsets;
import ghidrust.decompiler.parser.c.CVisitor; import ghidrust.decompiler.parser.c.CVisitor;
public class CParser/*@bgen(jjtree)*/implements CParserTreeConstants/*@egen*/ {/*@bgen(jjtree)*/ public class CParser/*@bgen(jjtree)*/implements CParserTreeConstants/*@egen*/ {/*@bgen(jjtree)*/
protected static JJTCParserState jjtree = new JJTCParserState(); protected JJTCParserState jjtree = new JJTCParserState();
/*@egen*/ /*@egen*/
private static CParser c_parser; private static CParser c_parser;
@@ -123,9 +124,10 @@ TOKEN : {
} }
TOKEN : { TOKEN : {
<IDENTIFIER: <LETTER> (<LETTER> | <DIGIT>)*> <IDENTIFIER: (<LETTER> | <SEPARATOR> <SEPARATOR>) (<LETTER> | <SEPARATOR> <SEPARATOR> | <DIGIT>)*>
| <#LETTER: ["$","A"-"Z","_","a"-"z"]> | <#LETTER: ["$","A"-"Z","_","a"-"z"]>
| <#DIGIT: ["0"-"9"]> | <#DIGIT: ["0"-"9"]>
| <#SEPARATOR: [":"]>
} }

View File

@@ -11,6 +11,7 @@ From: https://github.com/javacc/javacc/blob/master/grammars/CParser.jj
options { options {
MULTI = true; MULTI = true;
VISITOR = true; VISITOR = true;
STATIC = false;
} }
PARSER_BEGIN(CParser) PARSER_BEGIN(CParser)
@@ -119,9 +120,10 @@ TOKEN : {
} }
TOKEN : { TOKEN : {
<IDENTIFIER: <LETTER> (<LETTER> | <DIGIT>)*> <IDENTIFIER: (<LETTER> | <SEPARATOR> <SEPARATOR>) (<LETTER> | <SEPARATOR> <SEPARATOR> | <DIGIT>)*>
| <#LETTER: ["$","A"-"Z","_","a"-"z"]> | <#LETTER: ["$","A"-"Z","_","a"-"z"]>
| <#DIGIT: ["0"-"9"]> | <#DIGIT: ["0"-"9"]>
| <#SEPARATOR: [":"]>
} }