Rizin
unix-like reverse engineering framework and cli tools
create.c File Reference
#include <rz_flirt.h>
#include <rz_util.h>

Go to the source code of this file.

Macros

#define starts_with_flag(b, c)   (!strncmp(b, c, strlen(c)))
 

Functions

void module_free (RzFlirtModule *module)
 
ut16 flirt_crc16 (const ut8 *data_p, size_t length)
 
static void flirt_function_sanitize_name (RzFlirtFunction *function)
 
static RzFlirtFunctionflirt_function_new (const char *name, bool is_local, ut64 offset, ut64 address)
 
static RzFlirtModuleflirt_module_new (RzAnalysis *analysis, RzAnalysisFunction *func, const ut8 *buffer, const ut8 *mask, ut64 b_size, bool tail_bytes)
 
static RzFlirtNodeflirt_create_child (const ut8 *buffer, const ut8 *mask, ut32 b_size)
 
static RzFlirtNodeflirt_create_child_from_analysis (RzAnalysis *analysis, RzAnalysisFunction *func, const ut8 *buffer, const ut8 *mask, ut32 b_size, bool tail_bytes)
 
static bool is_valid_mask_prelude (const ut8 *buffer, ut32 b_size)
 
static int flirt_compare_module (const RzFlirtModule *a, const RzFlirtModule *b)
 
int flirt_compare_node (const RzFlirtNode *a, const RzFlirtNode *b)
 
static void flirt_node_shorten_pattern (RzFlirtNode *node, ut32 from)
 
static bool flirt_node_shorten_and_insert (const RzFlirtNode *root, RzFlirtNode *node)
 
bool flirt_node_optimize (RzFlirtNode *root)
 
RZ_API RZ_OWN RzFlirtNoderz_sign_flirt_node_new (RZ_NONNULL RzAnalysis *analysis, ut32 optimization)
 Generates the FLIRT signatures and returns an RzFlirtNode. More...
 

Detailed Description

Generates RzFlirtNodes from data contained in RzAnalysis.

Definition in file create.c.

Macro Definition Documentation

◆ starts_with_flag

#define starts_with_flag (   b,
  c 
)    (!strncmp(b, c, strlen(c)))

Definition at line 12 of file create.c.

Function Documentation

◆ flirt_compare_module()

static int flirt_compare_module ( const RzFlirtModule a,
const RzFlirtModule b 
)
static

Definition at line 216 of file create.c.

216  {
217  if (a->length != b->length) {
218  return a->length - b->length;
219  }
220  const RzFlirtFunction *af = rz_list_first(a->public_functions);
221  const RzFlirtFunction *bf = rz_list_first(b->public_functions);
222  return strcmp(af->name, bf->name);
223 }
RZ_API RZ_BORROW void * rz_list_first(RZ_NONNULL const RzList *list)
Returns the first element of the list.
Definition: list.c:77
#define b(i)
Definition: sha256.c:42
#define a(i)
Definition: sha256.c:41
char name[RZ_FLIRT_NAME_MAX]
Definition: rz_flirt.h:158

References a, b, rz_flirt_function_t::name, and rz_list_first().

Referenced by flirt_node_shorten_and_insert().

◆ flirt_compare_node()

int flirt_compare_node ( const RzFlirtNode a,
const RzFlirtNode b 
)

Definition at line 225 of file create.c.

225  {
226  if (a->pattern_mask[0] == 0xFF && b->pattern_mask[0] == 0xFF) {
227  return memcmp(a->pattern_bytes, b->pattern_bytes, RZ_MIN(a->length, b->length));
228  }
229  return a->pattern_mask[0] == 0xFF ? -1 : 1;
230 }
#define RZ_MIN(x, y)

References a, b, and RZ_MIN.

Referenced by flirt_node_optimize(), flirt_node_shorten_and_insert(), rz_sign_flirt_node_new(), and rz_sign_flirt_parse_string_pattern_from_buffer().

◆ flirt_crc16()

ut16 flirt_crc16 ( const ut8 data_p,
size_t  length 
)

Definition at line 204 of file flirt.c.

204  {
205  ut8 i;
206  ut32 data;
207  ut32 crc = 0xFFFF;
208 
209  if (length == 0) {
210  return 0;
211  }
212  do {
213  data = *data_p++;
214  for (i = 0; i < 8; i++) {
215  if ((crc ^ data) & 1) {
216  crc = (crc >> 1) ^ POLY;
217  } else {
218  crc >>= 1;
219  }
220  data >>= 1;
221  }
222  } while (--length > 0);
223 
224  crc = ~crc;
225  data = crc;
226  crc = (crc << 8) | ((data >> 8) & 0xff);
227  return (ut16)(crc);
228 }
lzma_index ** i
Definition: index.h:629
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len static semflg const void static shmflg const struct timespec struct timespec static rem const char static group const void length
Definition: sflib.h:133
uint16_t ut16
uint32_t ut32
#define POLY
Definition: flirt.c:203
uint8_t ut8
Definition: lh5801.h:11

References i, length, and POLY.

Referenced by flirt_module_new(), and module_match_buffer().

◆ flirt_create_child()

static RzFlirtNode* flirt_create_child ( const ut8 buffer,
const ut8 mask,
ut32  b_size 
)
static

Definition at line 126 of file create.c.

126  {
127  RzFlirtNode *child = RZ_NEW0(RzFlirtNode);
128  if (!child) {
129  RZ_LOG_ERROR("FLIRT: cannot allocate child node.\n");
130  goto fail;
131  }
132 
134  if (!child->child_list) {
135  RZ_LOG_ERROR("FLIRT: cannot allocate child module list.\n");
136  goto fail;
137  }
138 
140  if (!child->module_list) {
141  RZ_LOG_ERROR("FLIRT: cannot allocate child module list.\n");
142  goto fail;
143  }
144 
147  if (!child->pattern_bytes || !child->pattern_mask) {
148  RZ_LOG_ERROR("FLIRT: cannot allocate child pattern buffer.\n");
149  goto fail;
150  }
151 
152  if (b_size < RZ_FLIRT_MAX_PRELUDE_SIZE) {
153  memcpy(child->pattern_bytes, buffer, b_size);
154  memcpy(child->pattern_mask, mask, b_size);
155  child->length = b_size;
156  } else {
160  }
161 
162  child->variant_mask = 0;
163  for (ut32 i = 0; i < child->length; ++i) {
164  child->variant_mask <<= 1;
165  if (child->pattern_mask[i] != 0xff) {
166  child->variant_mask |= 1;
167  }
168  }
169 
170  return child;
171 
172 fail:
174  return NULL;
175 }
#define mask()
void module_free(RzFlirtModule *module)
Definition: flirt.c:284
#define NULL
Definition: cris-opc.c:27
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
RZ_API RZ_OWN RzList * rz_list_newf(RzListFree f)
Returns a new initialized RzList pointer and sets the free method.
Definition: list.c:248
void * malloc(size_t size)
Definition: malloc.c:123
RZ_API void rz_sign_flirt_node_free(RZ_NULLABLE RzFlirtNode *node)
Frees an RzFlirtNode struct.
Definition: flirt.c:299
#define RZ_FLIRT_MAX_PRELUDE_SIZE
Definition: rz_flirt.h:20
void(* RzListFree)(void *ptr)
Definition: rz_list.h:11
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
#define RZ_NEW0(x)
Definition: rz_types.h:284
Definition: buffer.h:15
RzList * child_list
Definition: rz_flirt.h:177
RzList * module_list
Definition: rz_flirt.h:178
ut8 * pattern_mask
Definition: rz_flirt.h:182
ut8 * pattern_bytes
Definition: rz_flirt.h:181
ut64 variant_mask
Definition: rz_flirt.h:180
#define fail(test)
Definition: tests.h:29

References rz_flirt_node_t::child_list, fail, i, rz_flirt_node_t::length, malloc(), mask, memcpy(), module_free(), rz_flirt_node_t::module_list, NULL, rz_flirt_node_t::pattern_bytes, rz_flirt_node_t::pattern_mask, RZ_FLIRT_MAX_PRELUDE_SIZE, rz_list_newf(), RZ_LOG_ERROR, RZ_MIN, RZ_NEW0, rz_sign_flirt_node_free(), and rz_flirt_node_t::variant_mask.

Referenced by flirt_create_child_from_analysis(), and flirt_node_shorten_and_insert().

◆ flirt_create_child_from_analysis()

static RzFlirtNode* flirt_create_child_from_analysis ( RzAnalysis analysis,
RzAnalysisFunction func,
const ut8 buffer,
const ut8 mask,
ut32  b_size,
bool  tail_bytes 
)
static

Definition at line 177 of file create.c.

177  {
178  RzFlirtNode *child = NULL;
180 
181  child = flirt_create_child(buffer, mask, b_size);
182  if (!child) {
183  goto fail;
184  }
185 
186  if (b_size <= RZ_FLIRT_MAX_PRELUDE_SIZE) {
187  module = flirt_module_new(analysis, func, NULL, NULL, 0, false);
188  } else {
190  }
191 
192  if (!module) {
193  goto fail;
194  } else if (!rz_list_append(child->module_list, module)) {
196  RZ_LOG_ERROR("FLIRT: cannot append module to child.\n");
197  goto fail;
198  }
199 
200  return child;
201 
202 fail:
204  return NULL;
205 }
static RzFlirtModule * flirt_module_new(RzAnalysis *analysis, RzAnalysisFunction *func, const ut8 *buffer, const ut8 *mask, ut64 b_size, bool tail_bytes)
Definition: create.c:63
static RzFlirtNode * flirt_create_child(const ut8 *buffer, const ut8 *mask, ut32 b_size)
Definition: create.c:126
RZ_API RZ_BORROW RzListIter * rz_list_append(RZ_NONNULL RzList *list, void *data)
Appends at the end of the list a new element.
Definition: list.c:288
Definition: sftypes.h:77

References fail, flirt_create_child(), flirt_module_new(), mask, module_free(), rz_flirt_node_t::module_list, NULL, RZ_FLIRT_MAX_PRELUDE_SIZE, rz_list_append(), RZ_LOG_ERROR, and rz_sign_flirt_node_free().

Referenced by rz_sign_flirt_node_new().

◆ flirt_function_new()

static RzFlirtFunction* flirt_function_new ( const char *  name,
bool  is_local,
ut64  offset,
ut64  address 
)
static

Definition at line 29 of file create.c.

29  {
30  if (name) {
31  if (starts_with_flag(name, "sym.")) {
32  name += strlen("sym.");
33  } else if (starts_with_flag(name, "flirt.")) {
34  name += strlen("flirt.");
35  }
36  }
37 
38  ut32 namelen = name ? strlen(name) : 0;
39  if (namelen >= RZ_FLIRT_NAME_MAX) {
40  RZ_LOG_WARN("FLIRT: function at %08" PFMT64x " exceeds the max name length (%u >= %u)\n", offset, namelen, RZ_FLIRT_NAME_MAX);
41  namelen = (RZ_FLIRT_NAME_MAX - 1);
42  }
43 
45  if (!function) {
46  RZ_LOG_ERROR("FLIRT: cannot allocate function\n");
47  return NULL;
48  }
49 
50  if (namelen > 0) {
51  strncpy(function->name, name, namelen);
53  } else {
54  rz_strf(function->name, "fcn.%08" PFMT64x, offset);
55  }
56 
57  function->offset = address - offset;
58  function->negative_offset = offset < address;
59  function->is_local = is_local;
60  return function;
61 }
#define starts_with_flag(b, c)
Definition: create.c:12
static void flirt_function_sanitize_name(RzFlirtFunction *function)
Definition: create.c:17
voidpf uLong offset
Definition: ioapi.h:144
#define RZ_FLIRT_NAME_MAX
Definition: rz_flirt.h:17
#define RZ_LOG_WARN(fmtstr,...)
Definition: rz_log.h:56
#define rz_strf(buf,...)
Convenience macro for local temporary strings.
Definition: rz_str.h:59
#define PFMT64x
Definition: rz_types.h:393
Definition: z80asm.h:102

References flirt_function_sanitize_name(), NULL, PFMT64x, RZ_FLIRT_NAME_MAX, RZ_LOG_ERROR, RZ_LOG_WARN, RZ_NEW0, rz_strf, and starts_with_flag.

Referenced by flirt_module_new().

◆ flirt_function_sanitize_name()

static void flirt_function_sanitize_name ( RzFlirtFunction function)
inlinestatic

Definition at line 17 of file create.c.

17  {
18  for (ut32 i = 0; i < RZ_FLIRT_NAME_MAX; ++i) {
19  char ch = function->name[i];
20  if (ch > ' ' && ch <= '~') {
21  continue;
22  } else if (!ch) {
23  break;
24  }
25  function->name[i] = '?';
26  }
27 }

References i, and RZ_FLIRT_NAME_MAX.

Referenced by flirt_function_new().

◆ flirt_module_new()

static RzFlirtModule* flirt_module_new ( RzAnalysis analysis,
RzAnalysisFunction func,
const ut8 buffer,
const ut8 mask,
ut64  b_size,
bool  tail_bytes 
)
static

Definition at line 63 of file create.c.

63  {
65  if (!module) {
66  RZ_LOG_ERROR("FLIRT: cannot allocate module\n");
67  return NULL;
68  }
69 
70  module->tail_bytes = rz_list_newf((RzListFree)free);
71  if (!module->tail_bytes) {
72  RZ_LOG_ERROR("FLIRT: cannot allocate module tail list\n");
73  goto fail;
74  }
75 
76  module->public_functions = rz_list_newf((RzListFree)free);
77  if (!module->public_functions) {
78  RZ_LOG_ERROR("FLIRT: cannot allocate module public function list\n");
79  goto fail;
80  }
81 
82  module->referenced_functions = rz_list_newf((RzListFree)free);
83  if (!module->referenced_functions) {
84  RZ_LOG_ERROR("FLIRT: cannot allocate module referenced function list\n");
85  goto fail;
86  }
87 
88  if (b_size > 0 && buffer) {
89  // the crc should be generated only for when the buffer is > RZ_FLIRT_MAX_PRELUDE_SIZE
90  module->crc_length = RZ_MIN(b_size, 0xFF);
91  module->crc16 = flirt_crc16(buffer, module->crc_length);
92  }
93 
95 
96  if (tail_bytes) {
97  for (ut32 i = 0; i < RZ_MIN(b_size, 0xFF); ++i) {
98  if (mask[i] != 0xff) {
99  continue;
100  }
102  if (!tb || !rz_list_append(module->tail_bytes, tb)) {
103  RZ_LOG_ERROR("FLIRT: cannot allocate or append tail byte to module list\n");
104  free(tb);
105  goto fail;
106  }
107  tb->offset = i;
108  tb->value = buffer[i];
109  }
110  }
111 
112  RzFlirtFunction *function = flirt_function_new(func->name, false, func->addr, func->addr);
113  if (!function || !rz_list_append(module->public_functions, function)) {
114  RZ_LOG_ERROR("FLIRT: cannot append function to public list\n");
115  free(function);
116  goto fail;
117  }
118 
119  return module;
120 
121 fail:
123  return NULL;
124 }
RZ_API ut64 rz_analysis_function_linear_size(RzAnalysisFunction *fcn)
Definition: function.c:318
static RzFlirtFunction * flirt_function_new(const char *name, bool is_local, ut64 offset, ut64 address)
Definition: create.c:29
ut16 flirt_crc16(const ut8 *data_p, size_t length)
Definition: flirt.c:204
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130

References rz_analysis_function_t::addr, fail, flirt_crc16(), flirt_function_new(), free(), i, mask, module_free(), rz_analysis_function_t::name, NULL, rz_flirt_tail_byte_t::offset, rz_analysis_function_linear_size(), rz_list_append(), rz_list_newf(), RZ_LOG_ERROR, RZ_MIN, RZ_NEW0, and rz_flirt_tail_byte_t::value.

Referenced by flirt_create_child_from_analysis().

◆ flirt_node_optimize()

bool flirt_node_optimize ( RzFlirtNode root)

Definition at line 316 of file create.c.

316  {
317  if (rz_list_length(root->child_list) < 1) {
318  return true;
319  }
320 
321  RzList *childs = root->child_list;
322 
324  if (!root->child_list) {
325  RZ_LOG_ERROR("FLIRT: cannot allocate child list.\n");
326  goto fail;
327  }
328 
330 
331  RzListIter *it;
332  RzFlirtNode *child;
333  rz_list_foreach (childs, it, child) {
334  it->data = NULL;
335  if (!flirt_node_shorten_and_insert(root, child)) {
336  goto fail;
337  }
338  }
339  rz_list_free(childs);
340 
341  return true;
342 
343 fail:
344  rz_list_free(childs);
345  return false;
346 }
int flirt_compare_node(const RzFlirtNode *a, const RzFlirtNode *b)
Definition: create.c:225
static bool flirt_node_shorten_and_insert(const RzFlirtNode *root, RzFlirtNode *node)
Definition: create.c:244
int root
Definition: enough.c:226
RZ_API void rz_list_sort(RZ_NONNULL RzList *list, RZ_NONNULL RzListComparator cmp)
Sorts via merge sort or via insertion sort a list.
Definition: list.c:743
RZ_API ut32 rz_list_length(RZ_NONNULL const RzList *list)
Returns the length of the list.
Definition: list.c:109
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
int(* RzListComparator)(const void *value, const void *list_data)
Definition: rz_list.h:33
void * data
Definition: rz_list.h:14

References rz_list_iter_t::data, fail, flirt_compare_node(), flirt_node_shorten_and_insert(), NULL, root, rz_list_free(), rz_list_length(), rz_list_newf(), rz_list_sort(), RZ_LOG_ERROR, and rz_sign_flirt_node_free().

Referenced by rz_sign_flirt_node_new(), and rz_sign_flirt_parse_string_pattern_from_buffer().

◆ flirt_node_shorten_and_insert()

static bool flirt_node_shorten_and_insert ( const RzFlirtNode root,
RzFlirtNode node 
)
static

Definition at line 244 of file create.c.

244  {
245  RzListIter *it;
246  RzFlirtNode *child;
247  RzFlirtNode *middle_node;
248  ut32 i;
249 
250  rz_list_foreach (root->child_list, it, child) {
251  for (i = 0; i < child->length && i < node->length; ++i) {
252  if (child->pattern_mask[i] != 0xFF && node->pattern_mask[i] != 0xFF) {
253  continue;
254  } else if (child->pattern_mask[i] != node->pattern_mask[i] ||
255  child->pattern_bytes[i] != node->pattern_bytes[i]) {
256  break;
257  }
258  }
259  if (i == 0) {
260  continue;
261  } else if (child->length == i && node->length == child->length) {
262  // same pattern just merge.
263  rz_list_join(child->module_list, node->module_list);
266  return true;
267  } else if (child->length == i) {
268  // partial pattern match but matches the child
270  if (!flirt_node_shorten_and_insert(child, node)) {
271  return false;
272  }
274  } else if (node->length == i) {
275  // partial pattern match but matches the node
276  it->data = node;
278  if (!rz_list_append(node->child_list, child)) {
279  RZ_LOG_ERROR("FLIRT: cannot append child to optimized list.\n");
281  return false;
282  }
283  } else {
284  // partial pattern match, requires to check the middle node
285  middle_node = flirt_create_child(child->pattern_bytes, child->pattern_mask, i);
286  if (!middle_node) {
288  return false;
289  }
290  it->data = middle_node;
291  if (!rz_list_append(middle_node->child_list, child)) {
292  RZ_LOG_ERROR("FLIRT: cannot append child to optimized list.\n");
295  return false;
296  } else if (!rz_list_append(middle_node->child_list, node)) {
297  RZ_LOG_ERROR("FLIRT: cannot append child to optimized list.\n");
299  return false;
300  }
304  }
305  return true;
306  }
307 
308  if (!rz_list_append(root->child_list, node)) {
309  RZ_LOG_ERROR("FLIRT: cannot shorten node or append child to optimized list.\n");
311  return false;
312  }
313  return true;
314 }
static void flirt_node_shorten_pattern(RzFlirtNode *node, ut32 from)
Definition: create.c:232
static int flirt_compare_module(const RzFlirtModule *a, const RzFlirtModule *b)
Definition: create.c:216
RZ_API bool rz_list_join(RZ_NONNULL RzList *list1, RZ_NONNULL RzList *list2)
Joins 2 list into one (list2 pointer needs to be freed by the user)
Definition: list.c:209

References rz_flirt_node_t::child_list, rz_list_iter_t::data, flirt_compare_module(), flirt_compare_node(), flirt_create_child(), flirt_node_shorten_pattern(), i, rz_flirt_node_t::length, rz_flirt_node_t::module_list, rz_flirt_node_t::pattern_bytes, rz_flirt_node_t::pattern_mask, root, rz_list_append(), rz_list_join(), rz_list_sort(), RZ_LOG_ERROR, and rz_sign_flirt_node_free().

Referenced by flirt_node_optimize().

◆ flirt_node_shorten_pattern()

static void flirt_node_shorten_pattern ( RzFlirtNode node,
ut32  from 
)
static

Definition at line 232 of file create.c.

232  {
233  if (from < 1) {
234  return;
235  }
236  node->length -= from;
237  memmove(node->pattern_bytes, node->pattern_bytes + from, node->length);
238  memmove(node->pattern_mask, node->pattern_mask + from, node->length);
239 
240  ut64 upper_mask = ~(UT64_MAX << node->length);
241  node->variant_mask &= upper_mask;
242 }
#define UT64_MAX
Definition: rz_types_base.h:86
static struct sockaddr static addrlen static backlog const void static flags void struct sockaddr from
Definition: sfsocketcall.h:123
ut64(WINAPI *w32_GetEnabledXStateFeatures)()

References from, rz_flirt_node_t::length, rz_flirt_node_t::pattern_bytes, rz_flirt_node_t::pattern_mask, ut64(), UT64_MAX, and rz_flirt_node_t::variant_mask.

Referenced by flirt_node_shorten_and_insert().

◆ is_valid_mask_prelude()

static bool is_valid_mask_prelude ( const ut8 buffer,
ut32  b_size 
)
inlinestatic

Definition at line 207 of file create.c.

207  {
208  for (ut32 i = 0; i < RZ_MIN(RZ_FLIRT_MAX_PRELUDE_SIZE, b_size); ++i) {
209  if (buffer[i] == 0xff) {
210  return true;
211  }
212  }
213  return false;
214 }

References i, RZ_FLIRT_MAX_PRELUDE_SIZE, and RZ_MIN.

Referenced by rz_sign_flirt_node_new().

◆ module_free()

void module_free ( RzFlirtModule module)

Definition at line 284 of file flirt.c.

284  {
285  if (!module) {
286  return;
287  }
288  rz_list_free(module->public_functions);
289  rz_list_free(module->tail_bytes);
290  rz_list_free(module->referenced_functions);
291  free(module);
292 }

References free(), and rz_list_free().

Referenced by flirt_create_child(), flirt_create_child_from_analysis(), and flirt_module_new().

◆ rz_sign_flirt_node_new()

RZ_API RZ_OWN RzFlirtNode* rz_sign_flirt_node_new ( RZ_NONNULL RzAnalysis analysis,
ut32  optimization 
)

Generates the FLIRT signatures and returns an RzFlirtNode.

Parameters
analysisThe RzAnalysis structure to derive the signatures.
optimizationOptimization to apply after creation of the flatten nodes.
Returns
Generated FLIRT root node.

Definition at line 355 of file create.c.

355  {
356  rz_return_val_if_fail(analysis && analysis->coreb.core, NULL);
357  if (optimization > RZ_FLIRT_NODE_OPTIMIZE_MAX) {
358  RZ_LOG_ERROR("FLIRT: optimization value is invalid (%u > RZ_FLIRT_NODE_OPTIMIZE_MAX).\n", optimization);
359  return NULL;
360  }
361 
362  if (rz_list_length(analysis->fcns) < 1) {
363  RZ_LOG_ERROR("FLIRT: There are no analyzed functions. Have you run 'aa'?\n");
364  return NULL;
365  }
366  bool tail_bytes = optimization != RZ_FLIRT_NODE_OPTIMIZE_MAX;
368  if (!root) {
369  RZ_LOG_ERROR("FLIRT: cannot allocate root node.\n");
370  return NULL;
371  }
373 
374  RzListIter *it;
375  RzAnalysisFunction *func;
376  rz_list_foreach (analysis->fcns, it, func) {
377  ut64 func_size = rz_analysis_function_linear_size(func);
378  if (!func->name) {
379  RZ_LOG_ERROR("FLIRT: function at 0x%" PFMT64x " has a null name. skipping function...\n", func->addr);
380  continue;
381  } else if ((func->type != RZ_ANALYSIS_FCN_TYPE_FCN &&
382  func->type != RZ_ANALYSIS_FCN_TYPE_LOC &&
383  func->type != RZ_ANALYSIS_FCN_TYPE_SYM) ||
384  func_size < 1 ||
385  starts_with_flag(func->name, "imp.") ||
386  starts_with_flag(func->name, "sym.imp.")) {
387  continue;
388  }
389 
390  if (func_size > ST32_MAX) {
391  RZ_LOG_ERROR("FLIRT: this function exceeds the max size allowed by iob->read_at.\n");
392  RZ_LOG_ERROR("FLIRT: this should never happen. please open a bug report.\n");
393  goto fail;
394  }
395 
396  ut8 *pattern = malloc(func_size);
397  if (!pattern) {
398  RZ_LOG_ERROR("FLIRT: cannot allocate function buffer.\n");
399  goto fail;
400  }
401 
402  if (!analysis->iob.read_at(analysis->iob.io, func->addr, pattern, (int)func_size)) {
403  RZ_LOG_WARN("FLIRT: couldn't read function %s at 0x%" PFMT64x ".\n", func->name, func->addr);
404  free(pattern);
405  continue;
406  }
407 
408  ut8 *mask = rz_analysis_mask(analysis, func_size, pattern, func->addr);
409  if (!mask) {
410  RZ_LOG_ERROR("FLIRT: cannot calculate pattern mask.\n");
411  free(pattern);
412  goto fail;
413  } else if (!is_valid_mask_prelude(mask, func_size)) {
414  free(pattern);
415  free(mask);
416  continue;
417  }
418 
419  for (ut32 i = func_size - 1; i > 1; --i) {
420  if (mask[i] != 0xFF) {
421  func_size--;
422  continue;
423  }
424  break;
425  }
426 
427  RzFlirtNode *child = flirt_create_child_from_analysis(analysis, func, pattern, mask, func_size, tail_bytes);
428  RZ_FREE(pattern);
429  free(mask);
430  if (!child || !rz_list_append(root->child_list, child)) {
431  RZ_LOG_ERROR("FLIRT: cannot append child to root list.\n");
433  goto fail;
434  }
435  }
436 
437  if (rz_list_length(root->child_list) < 1) {
438  RZ_LOG_ERROR("FLIRT: cannot create signature file when i do not have signatures.\n");
439  goto fail;
440  }
441 
442  if (optimization == RZ_FLIRT_NODE_OPTIMIZE_NONE) {
444  } else if (!flirt_node_optimize(root)) {
445  goto fail;
446  }
447 
448  return root;
449 
450 fail:
452  return NULL;
453 }
RZ_API ut8 * rz_analysis_mask(RzAnalysis *analysis, ut32 size, const ut8 *data, ut64 at)
Definition: analysis.c:334
static RzFlirtNode * flirt_create_child_from_analysis(RzAnalysis *analysis, RzAnalysisFunction *func, const ut8 *buffer, const ut8 *mask, ut32 b_size, bool tail_bytes)
Definition: create.c:177
bool flirt_node_optimize(RzFlirtNode *root)
Definition: create.c:316
static bool is_valid_mask_prelude(const ut8 *buffer, ut32 b_size)
Definition: create.c:207
@ RZ_ANALYSIS_FCN_TYPE_SYM
Definition: rz_analysis.h:195
@ RZ_ANALYSIS_FCN_TYPE_LOC
Definition: rz_analysis.h:194
@ RZ_ANALYSIS_FCN_TYPE_FCN
Definition: rz_analysis.h:193
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
@ RZ_FLIRT_NODE_OPTIMIZE_NONE
keeps the structure flattened (keep the tail bytes)
Definition: rz_flirt.h:186
@ RZ_FLIRT_NODE_OPTIMIZE_MAX
optimize the tree structure and drops the tail bytes
Definition: rz_flirt.h:188
#define RZ_FREE(x)
Definition: rz_types.h:369
#define ST32_MAX
Definition: rz_types_base.h:97

References rz_analysis_function_t::addr, fail, flirt_compare_node(), flirt_create_child_from_analysis(), flirt_node_optimize(), free(), i, is_valid_mask_prelude(), malloc(), mask, rz_analysis_function_t::name, NULL, PFMT64x, root, RZ_ANALYSIS_FCN_TYPE_FCN, RZ_ANALYSIS_FCN_TYPE_LOC, RZ_ANALYSIS_FCN_TYPE_SYM, rz_analysis_function_linear_size(), rz_analysis_mask(), RZ_FLIRT_NODE_OPTIMIZE_MAX, RZ_FLIRT_NODE_OPTIMIZE_NONE, RZ_FREE, rz_list_append(), rz_list_length(), rz_list_newf(), rz_list_sort(), RZ_LOG_ERROR, RZ_LOG_WARN, RZ_NEW0, rz_return_val_if_fail, rz_sign_flirt_node_free(), ST32_MAX, starts_with_flag, rz_analysis_function_t::type, and ut64().

Referenced by rz_core_flirt_create_file().