forked from allthingsida/GraphSlick
-
Notifications
You must be signed in to change notification settings - Fork 0
/
algo.hpp
259 lines (226 loc) · 6.87 KB
/
algo.hpp
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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
#ifndef __ALGO__
#define __ALGO__
/*--------------------------------------------------------------------------
GraphSlick (c) Elias Bachaalany
-------------------------------------
Algorithms module
This module implements various algorithms used by the plugin
History
--------
10/23/2013 - eliasb - First version, it comes from refactored code from the plugin module
10/24/2013 - eliasb - Renamed class to a function like name and dropped the () operator
10/25/2013 - eliasb - Return the ndl2id map to the caller
- added 'append_node_id' param to func_to_mgraph()
10/28/2013 - eliasb - add 'hint' value to the combined blocks
- show the 'groupname' or 'id' as text for combined nodes
10/29/2013 - eliasb - added sanity checks to fc_to_combined_mg()
- functions don't compute flowchart each time now. user can pass a flowchart
- added sanitize_groupman() to allow loaded incomplete bbgroup file
11/01/2013 - eliasb - Now sanitize_groupman()' sanitized the path SGL only
- Added build_groupman_from_fc and build_groupman_from_3dvec functions
04/10/2014 - eliasb - fix: Auto increment SG number when building the info from BBMatch!Analyze()
--------------------------------------------------------------------------*/
//--------------------------------------------------------------------------
#include <map>
#include <pro.h>
#include <funcs.hpp>
#include <gdl.hpp>
#include <graph.hpp>
#include "groupman.h"
#include "util.h"
//--------------------------------------------------------------------------
/**
* @brief Creates a mutable graph that have the combined nodes per the groupmanager
* A class was used to simulate nested functions needed by the combine algo
*/
class fc_to_combined_mg
{
// Create a mapping between single node ids and the nodedef list they belong to
ng2nid_t *group2id;
gnodemap_t *node_map;
groupman_t *gm;
qflow_chart_t *fc;
bool show_nids_only;
/**
* @brief Create and return a groupped node ID
*/
int get_groupid(int n)
{
int group_id;
// Find how this single node is defined in the group manager
nodeloc_t *loc = gm->find_nodeid_loc(n);
if (loc == NULL)
return -1;
// Does this node have a group yet? (ndl)
ng2nid_t::iterator it = group2id->find(loc->ng);
if (it == group2id->end())
{
// Assign an auto-increment id
group_id = group2id->size();
(*group2id)[loc->ng] = group_id;
// Initialize this group's node id
gnode_t gn;
gn.id = group_id;
size_t t = loc->ng->size();
for (nodegroup_t::iterator it=loc->ng->begin();
it != loc->ng->end();
++it)
{
if (show_nids_only)
{
gn.text.cat_sprnt("%d", (*it)->nid);
if (--t > 0)
gn.text.append(", ");
}
qbasic_block_t &block = fc->blocks[(*it)->nid];
qstring s;
get_disasm_text(
block.startEA,
block.endEA,
&s);
gn.hint.append(s);
}
if (!show_nids_only)
{
// Are there any groupped nodes?
if (loc->ng->size() > 1)
{
//TODO: OPTION: enlarge groupped label
gn.text.append("\n\n\n");
// Display the group name or the group id
gn.text.append(loc->sg->get_display_name());
gn.text.append("\n\n\n");
}
else
{
gn.text = gn.hint;
}
}
// Cache the node data
(*node_map)[group_id] = gn;
}
else
{
// Grab the group id
group_id = it->second;
}
return group_id;
}
/**
* @brief Build the combined mutable graph from the groupman and a flowchart
*/
bool build(
qflow_chart_t *fc,
groupman_t *gm,
gnodemap_t &node_map,
ng2nid_t &group2id,
mutable_graph_t *mg)
{
// Take a reference to the local variables so they are used
// in the other helper functions
this->gm = gm;
this->node_map = &node_map;
this->fc = fc;
this->group2id = &group2id;
// Compute the total size of nodes needed for the combined graph
// The size is the total count of node def lists in each group def
size_t node_count = 0;
for (supergroup_listp_t::iterator it=gm->get_path_sgl()->begin();
it != gm->get_path_sgl()->end();
++it)
{
psupergroup_t sg = *it;
node_count += sg->gcount();
}
// Resize the graph
mg->resize(node_count);
// Build the combined graph
int snodes_count = fc->size();
for (int nid=0; nid < snodes_count; nid++)
{
// Figure out the combined node ID
int group_id = get_groupid(nid);
if (group_id == -1)
return false;
// Build the edges
for (int isucc=0, succ_sz=fc->nsucc(nid);
isucc < succ_sz;
isucc++)
{
// Get the successor node
int nid_succ = fc->succ(nid, isucc);
// This node belongs to the same group?
int succ_grid = get_groupid(nid_succ);
if (succ_grid == -1)
return false;
if (succ_grid == group_id)
{
// Do nothing, consider as one node
continue;
}
// Add an edge
mg->add_edge(group_id, succ_grid, NULL);
}
}
return true;
}
public:
/**
* @brief Operator to call the class as a function
*/
fc_to_combined_mg(
ea_t func_ea,
groupman_t *gm,
gnodemap_t &node_map,
ng2nid_t &group2id,
mutable_graph_t *mg,
qflow_chart_t *fc = NULL): show_nids_only(false)
{
// Build function's flowchart (if needed)
qflow_chart_t _fc;
if (fc == NULL)
{
fc = &_fc;
if (!get_func_flowchart(func_ea, *fc))
return;
}
build(fc, gm, node_map, group2id, mg);
}
};
//--------------------------------------------------------------------------
/**
* @brief Build a mutable graph from a function address
*/
bool func_to_mgraph(
ea_t func_ea,
mutable_graph_t *mg,
gnodemap_t &node_map,
qflow_chart_t *fc = NULL,
bool append_node_id = false);
//--------------------------------------------------------------------------
/**
* @brief Build the groupman with each node in its node group and super group
*/
void build_groupman_from_fc(
qflow_chart_t *fc,
groupman_t *gm,
bool sanitize);
//--------------------------------------------------------------------------
/**
* @brief Build the group manager from another groupman defined in a 3d int vec
*/
void build_groupman_from_3dvec(
qflow_chart_t *fc,
int_3dvec_t &path,
groupman_t *gm,
bool sanitize);
//--------------------------------------------------------------------------
/**
* @brief Sanitize the contents of the groupman path SGL versus the flowchart
of the function
*/
bool sanitize_groupman(
ea_t func_ea,
groupman_t *gm,
qflow_chart_t *fc = NULL);
#endif