-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy path2525-Decompiler-Add-C-deincrement-and-increment-oper.patch
151 lines (147 loc) · 7.52 KB
/
2525-Decompiler-Add-C-deincrement-and-increment-oper.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Grant Hernandez <[email protected]>
Date: Sun, 22 Nov 2020 19:17:54 -0500
Subject: [PATCH] 2525: Decompiler: Add C deincrement and increment operator
Add increment and decrement ops
Add post inc/dec ops to avoid parens
---
.../Decompiler/src/decompile/cpp/printc.cc | 43 +++++++++++++++++++
.../Decompiler/src/decompile/cpp/printc.hh | 5 +++
.../src/decompile/cpp/printlanguage.cc | 11 +++++
.../src/decompile/cpp/printlanguage.hh | 3 +-
4 files changed, 61 insertions(+), 1 deletion(-)
diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/printc.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/printc.cc
index e779b8aa55..a6d429e60c 100644
--- a/Ghidra/Features/Decompiler/src/decompile/cpp/printc.cc
+++ b/Ghidra/Features/Decompiler/src/decompile/cpp/printc.cc
@@ -30,6 +30,10 @@ OpToken PrintC::bitwise_not = { "~", "", 1, 62, false, OpToken::unary_prefix, 0,
OpToken PrintC::boolean_not = { "!", "", 1, 62, false, OpToken::unary_prefix, 0, 0, (OpToken *)0 };
OpToken PrintC::unary_minus = { "-", "", 1, 62, false, OpToken::unary_prefix, 0, 0, (OpToken *)0 };
OpToken PrintC::unary_plus = { "+", "", 1, 62, false, OpToken::unary_prefix, 0, 0, (OpToken *)0 };
+OpToken PrintC::pre_increment = { "++", "", 1, 66, false, OpToken::unary_prefix, 0, 0, (OpToken *)0 };
+OpToken PrintC::pre_decrement = { "--", "", 1, 66, false, OpToken::unary_prefix, 0, 0, (OpToken *)0 };
+OpToken PrintC::post_increment = { "++", "", 1, 66, false, OpToken::unary_postfix, 0, 0, (OpToken *)0 };
+OpToken PrintC::post_decrement = { "--", "", 1, 66, false, OpToken::unary_postfix, 0, 0, (OpToken *)0 };
OpToken PrintC::addressof = { "&", "", 1, 62, false, OpToken::unary_prefix, 0, 0, (OpToken *)0 };
OpToken PrintC::dereference = { "*", "", 1, 62, false, OpToken::unary_prefix, 0, 0, (OpToken *)0 };
OpToken PrintC::typecast = { "(", ")", 2, 62, false, OpToken::presurround, 0, 0, (OpToken *)0 };
@@ -2394,6 +2398,44 @@ void PrintC::docTypeDefinitions(const TypeFactory *typegrp)
}
}
+/// Check that the given p-code can be simplified to a C increment or decrement operator.
+/// \param op is the given PcodeOp
+bool PrintC::emitIncDecOp(const PcodeOp *op)
+
+{
+ const OpToken * token;
+ enum OpCode opcode = op->code();
+
+ if (opcode != CPUI_INT_ADD && opcode != CPUI_INT_SUB) return false;
+
+ // is operation modifying inplace?
+ const Varnode *vn = op->getIn(0);
+ if (op->getOut()->getHigh() != vn->getHigh()) return false;
+
+ // get add/sub value
+ const Varnode *value = op->getIn(1);
+
+ if (!value->isConstant()) return false;
+
+ int4 num = (int4)value->getAddr().getOffset();
+
+ // invert subtraction
+ if (opcode == CPUI_INT_SUB)
+ num = -num;
+
+ if (num == 1) {
+ token = &post_increment;
+ } else if (num == -1) {
+ token = &post_decrement;
+ } else {
+ return false;
+ }
+
+ pushOp(token,op);
+ pushVnExplicit(vn,op);
+ return true;
+}
+
/// Check that the given p-code op has an \e in-place token form and if the first input and the output
/// are references to the same variable. If so, emit the expression using the \e in-place token.
/// \param op is the given PcodeOp
@@ -2453,6 +2495,7 @@ void PrintC::emitExpression(const PcodeOp *op)
{
const Varnode *outvn = op->getOut();
if (outvn != (Varnode *)0) {
+ if (option_inplace_ops && emitIncDecOp(op)) return;
if (option_inplace_ops && emitInplaceOp(op)) return;
pushOp(&assignment,op);
pushSymbolDetail(outvn,op,false);
diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/printc.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/printc.hh
index 3cebbc3f91..b1b9988d41 100644
--- a/Ghidra/Features/Decompiler/src/decompile/cpp/printc.hh
+++ b/Ghidra/Features/Decompiler/src/decompile/cpp/printc.hh
@@ -75,6 +75,10 @@ protected:
static OpToken boolean_not; ///< The \e boolean \e not operator
static OpToken unary_minus; ///< The \e unary \e minus operator
static OpToken unary_plus; ///< The \e unary \e plus operator
+ static OpToken pre_increment; ///< The \e pre increment \e operator
+ static OpToken pre_decrement; ///< The \e pre decrement \e operator
+ static OpToken post_increment; ///< The \e post increment \e operator
+ static OpToken post_decrement; ///< The \e post decrement \e operator
static OpToken addressof; ///< The \e address \e of operator
static OpToken dereference; ///< The \e pointer \e dereference operator
static OpToken typecast; ///< The \e type \e cast operator
@@ -185,6 +189,7 @@ protected:
void emitGlobalVarDeclsRecursive(Scope *symScope); ///< Emit variable declarations for all global symbols under given scope
void emitLocalVarDecls(const Funcdata *fd); ///< Emit variable declarations for a function
void emitStatement(const PcodeOp *inst); ///< Emit a statement in the body of a function
+ bool emitIncDecOp(const PcodeOp *op); ///< Attempt to emit a increment or deincrement expression
bool emitInplaceOp(const PcodeOp *op); ///< Attempt to emit an expression rooted at an \e in-place operator
void emitGotoStatement(const FlowBlock *bl,const FlowBlock *exp_bl,uint4 type);
void emitSwitchCase(int4 casenum,const BlockSwitch *switchbl); ///< Emit labels for a \e case block
diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/printlanguage.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/printlanguage.cc
index cee8630e70..12fc94dd14 100644
--- a/Ghidra/Features/Decompiler/src/decompile/cpp/printlanguage.cc
+++ b/Ghidra/Features/Decompiler/src/decompile/cpp/printlanguage.cc
@@ -290,6 +290,12 @@ bool PrintLanguage::parentheses(const OpToken *op2)
// if (associative && (this == &op2)) return false;
if ((op2->type==OpToken::unary_prefix)||(op2->type==OpToken::presurround)) return false;
return true;
+ case OpToken::unary_postfix:
+ if (topToken->precedence > op2->precedence) return true;
+ if (topToken->precedence < op2->precedence) return false;
+ // if (associative && (this == &op2)) return false;
+ if (op2->type==OpToken::postsurround) return false;
+ return true;
case OpToken::postsurround:
if (stage==1) return false; // Inside the surround
if (topToken->precedence > op2->precedence) return true;
@@ -340,6 +346,11 @@ void PrintLanguage::emitOp(const ReversePolish &entry)
emit->tagOp(entry.tok->print1,EmitMarkup::no_color,entry.op);
emit->spaces(entry.tok->spacing,entry.tok->bump);
break;
+ case OpToken::unary_postfix:
+ if (entry.visited!=1) return;
+ emit->tagOp(entry.tok->print1,EmitMarkup::no_color,entry.op);
+ emit->spaces(entry.tok->spacing,entry.tok->bump);
+ break;
case OpToken::postsurround:
if (entry.visited==0) return;
if (entry.visited==1) { // Front surround token
diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/printlanguage.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/printlanguage.hh
index 7cdb7069cf..06bd5595eb 100644
--- a/Ghidra/Features/Decompiler/src/decompile/cpp/printlanguage.hh
+++ b/Ghidra/Features/Decompiler/src/decompile/cpp/printlanguage.hh
@@ -90,7 +90,8 @@ public:
postsurround, ///< Function or array operator form
presurround, ///< Modifier form (like a cast operation)
space, ///< No explicitly printed token
- hiddenfunction ///< Operation that isn't explicitly printed
+ hiddenfunction, ///< Operation that isn't explicitly printed
+ unary_postfix ///< Unary operator form (printed after its input)
};
string print1; ///< Printing characters for the token
string print2; ///< (terminating) characters for the token
--
2.45.1