Rizin
unix-like reverse engineering framework and cli tools
pat.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2021 RizinOrg <info@rizin.re>
2 // SPDX-FileCopyrightText: 2021 deroad <wargio@libero.it>
3 // SPDX-License-Identifier: LGPL-3.0-only
4 
43 #include <rz_flirt.h>
44 #include <rz_util.h>
45 
46 #if 0
47 #define pat_dbg(...) eprintf(__VA_ARGS__)
48 #else
49 #define pat_dbg(...)
50 #endif
51 
52 #define PAT_LINE_BUFFER_SIZE 1024
53 
54 extern void module_free(RzFlirtModule *module);
56 extern int flirt_compare_node(const RzFlirtNode *a, const RzFlirtNode *b);
57 
58 static inline ut8 decode_byte(char b) {
59  if (b >= '0' && b <= '9') {
60  return b - '0';
61  } else if (b >= 'A' && b <= 'F') {
62  return (b - 'A') + 10;
63  }
64  return (b - 'a') + 10;
65 }
66 
67 static inline ut8 parse_byte(char high, char low) {
68  ut8 value = decode_byte(high) << 4;
69  return value | decode_byte(low);
70 }
71 
72 static bool flirt_pat_parse_pattern_mask(const char *in_pattern, RzFlirtNode *child) {
73  size_t length = 0;
74  ut8 *bytes = NULL, *mask = NULL;
75 
76  if (RZ_STR_ISEMPTY(in_pattern)) {
77  return false;
78  }
79 
80  length = strlen(in_pattern);
81  if (length & 1) {
82  return false;
83  }
84 
85  ut32 n_bytes = length >> 1;
86 
87  bytes = RZ_NEWS(ut8, n_bytes);
88  if (!bytes) {
89  RZ_LOG_ERROR("FLIRT: cannot allocate child bytes\n");
90  return false;
91  }
92 
93  mask = RZ_NEWS(ut8, n_bytes);
94  if (!mask) {
95  RZ_LOG_ERROR("FLIRT: cannot allocate child mask\n");
96  goto err;
97  }
98 
99  child->variant_mask = 0;
100  for (ut32 i = 0; i < n_bytes; ++i) {
101  child->variant_mask <<= 1;
102  ut32 p = i << 1;
103  char high = in_pattern[p];
104  char low = in_pattern[p + 1];
105  if (IS_HEXCHAR(high) && IS_HEXCHAR(low)) {
106  bytes[i] = parse_byte(high, low);
107  mask[i] = 0xFF;
108  } else if (high == '.' && low == '.') {
109  bytes[i] = 0;
110  mask[i] = 0;
111  child->variant_mask |= 1;
112  } else {
113  goto err;
114  }
115  }
116 
117  child->pattern_bytes = bytes;
118  child->pattern_mask = mask;
119  child->length = n_bytes;
120  return true;
121 
122 err:
123  child->variant_mask = 0;
124  free(mask);
125  free(bytes);
126  return false;
127 }
128 
140 static bool flirt_pat_parse_line(RzFlirtNode *root, RzStrBuf *sb, ut32 line_num, bool tail_bytes) {
141  RzFlirtNode *child = NULL;
143  char *tmp_tok = NULL;
144 
145  int line_len = rz_strbuf_length(sb);
146  char *line = rz_strbuf_get(sb);
147  if (!strncmp(line, "---", strlen("---"))) {
148  return false;
149  } else if (line[0] == '#') {
150  return true;
151  }
152 
153  if (line[line_len - 1] == '\r') {
154  line_len--;
155  line[line_len] = 0;
156  if (*line || line_len < 1) {
157  RZ_LOG_WARN("FLIRT: line %u is empty\n", line_num);
158  return true;
159  }
160  }
161 
162  RzList *tokens = rz_str_split_list(line, " ", 0);
163  if (rz_list_empty(tokens)) {
164  RZ_LOG_ERROR("FLIRT: cannot tokenize line %u\n", line_num);
165  goto err;
166  }
167 
168  child = RZ_NEW0(RzFlirtNode);
169  if (!child) {
170  RZ_LOG_ERROR("FLIRT: cannot allocate child node\n");
171  goto err;
172  }
173 
175  if (!child->module_list) {
176  RZ_LOG_ERROR("FLIRT: cannot allocate child module list\n");
177  goto err;
178  }
179 
181  if (!module || !rz_list_append(child->module_list, module)) {
182  free(module);
183  RZ_LOG_ERROR("FLIRT: cannot allocate or append child module\n");
184  goto err;
185  }
186 
187  module->public_functions = rz_list_newf((RzListFree)free);
188  if (!module->public_functions) {
189  RZ_LOG_ERROR("FLIRT: cannot allocate child module public function list\n");
190  goto err;
191  }
192 
193  module->referenced_functions = rz_list_newf((RzListFree)free);
194  if (!module->public_functions) {
195  RZ_LOG_ERROR("FLIRT: cannot allocate child module referenced function list\n");
196  goto err;
197  }
198 
199  // Pattern with mask
200  // 4154554889FD534889F3C60700E8........C6441DFF004189C485C07515BE2E
201  // 31C04885D2741F488D4417FF4839C77610EB1D0F1F4400004883E8014839C777
202  tmp_tok = (char *)rz_list_pop_head(tokens);
203  if (!flirt_pat_parse_pattern_mask(tmp_tok, child)) {
204  RZ_LOG_ERROR("FLIRT: invalid pattern with mask (%s) at line %u\n", tmp_tok, line_num);
205  goto err;
206  }
207  pat_dbg("pattern: %s\n", tmp_tok);
208 
209  // CRC16 length
210  // [...] 07
211  // [...] 13
212  tmp_tok = (char *)rz_list_pop_head(tokens);
213  if (tmp_tok && strlen(tmp_tok) == 2 && IS_HEXCHAR(tmp_tok[0]) && IS_HEXCHAR(tmp_tok[1])) {
214  module->crc_length = parse_byte(tmp_tok[0], tmp_tok[1]);
215  } else {
216  RZ_LOG_ERROR("FLIRT: invalid crc16 length (%s) at line %u\n", tmp_tok, line_num);
217  goto err;
218  }
219  pat_dbg("crc16 length: %s\n", tmp_tok);
220 
221  // CRC16 value
222  // [...] FAEE
223  // [...] 9867
224  tmp_tok = (char *)rz_list_pop_head(tokens);
225  if (tmp_tok && strlen(tmp_tok) == 4 &&
226  IS_HEXCHAR(tmp_tok[0]) && IS_HEXCHAR(tmp_tok[1]) &&
227  IS_HEXCHAR(tmp_tok[2]) && IS_HEXCHAR(tmp_tok[3])) {
228  module->crc16 = parse_byte(tmp_tok[0], tmp_tok[1]) << 8;
229  module->crc16 |= parse_byte(tmp_tok[2], tmp_tok[3]);
230  } else {
231  RZ_LOG_ERROR("FLIRT: invalid crc16 value (%s) at line %u\n", tmp_tok, line_num);
232  goto err;
233  }
234  pat_dbg("crc16: %s\n", tmp_tok);
235 
236  // function size (min 2 bytes, but can be bigger)
237  // [...] 003B
238  // [...] 0033
239  tmp_tok = (char *)rz_list_pop_head(tokens);
240  if (!tmp_tok || strlen(tmp_tok) < 4 || !(module->length = strtol(tmp_tok, NULL, 16))) {
241  RZ_LOG_ERROR("FLIRT: invalid function size (%s) at line %u\n", tmp_tok, line_num);
242  goto err;
243  }
244  pat_dbg("function size: %s\n", tmp_tok);
245 
246  // symbols
247  // :0000@ Curl_gethostname ^000E gethostname ^0027 strchr
248  // :0000 Curl_memrchr
249  while ((tmp_tok = (char *)rz_list_pop_head(tokens)) && RZ_STR_ISNOTEMPTY(tmp_tok)) {
250  RzList *to_append = NULL;
251  ut32 len_tok = strlen(tmp_tok);
252  ut32 offset = 0;
253  bool is_local = false;
254  if (len_tok > 0 && !(len_tok & 1) && (IS_HEXCHAR(tmp_tok[0]) || tmp_tok[0] == '.')) {
255  // it's trailer bytes
256  break;
257  }
258 
259  if (len_tok >= 6 && tmp_tok[0] == ':' && tmp_tok[len_tok - 1] == '@') {
260  // :0000@ -> local function (handling it as public)
261  tmp_tok[len_tok - 1] = 0;
262  offset = strtol(tmp_tok + 1, NULL, 16);
263  is_local = true;
264  to_append = module->public_functions;
265  tmp_tok[len_tok - 1] = '@';
266  } else if (len_tok >= 5 && tmp_tok[0] == ':') {
267  // :0000 -> public function
268  offset = strtol(tmp_tok + 1, NULL, 16);
269  to_append = module->public_functions;
270  } else if (len_tok == 5 && tmp_tok[0] == '^') {
271  // ^0000 -> reference function
272  offset = strtol(tmp_tok + 1, NULL, 16);
273  to_append = module->referenced_functions;
274  } else {
275  RZ_LOG_ERROR("FLIRT: invalid symbol offset (%.10s len %u) at line %u\n", tmp_tok, len_tok, line_num);
276  goto err;
277  }
278 
279  tmp_tok = (char *)rz_list_pop_head(tokens);
280  if (RZ_STR_ISEMPTY(tmp_tok)) {
281  RZ_LOG_ERROR("FLIRT: empty symbol name at line %u\n", line_num);
282  goto err;
283  }
284  len_tok = strlen(tmp_tok);
285 
287  if (!function || !rz_list_append(to_append, function)) {
288  free(function);
289  RZ_LOG_ERROR("FLIRT: cannot allocate or append RzFlirtFunction\n");
290  goto err;
291  }
292  function->is_local = is_local;
293  function->offset = offset;
294  strncpy(function->name, tmp_tok, RZ_MIN(len_tok, RZ_FLIRT_NAME_MAX - 1));
295  pat_dbg("%s function: %04x %s\n", to_append == module->referenced_functions ? "ref" : (function->is_local ? "loc" : "pub"), offset, tmp_tok);
296  }
297 
298  if (tail_bytes && RZ_STR_ISNOTEMPTY(tmp_tok) && (IS_HEXCHAR(tmp_tok[0]) || tmp_tok[0] == '.')) {
299  size_t len_tok = strlen(tmp_tok);
300 
301  module->tail_bytes = rz_list_newf((RzListFree)free);
302  if (!module->public_functions) {
303  RZ_LOG_ERROR("FLIRT: cannot allocate child module tail bytes list\n");
304  goto err;
305  }
306 
307  for (ut32 i = 0, o = 0; i < len_tok && rz_list_length(module->tail_bytes) < 0xFF; i += 2, o++) {
308  if (tmp_tok[i] == '.' && tmp_tok[i + 1] == '.') {
309  continue;
310  } else if (!IS_HEXCHAR(tmp_tok[i]) || !IS_HEXCHAR(tmp_tok[i + 1])) {
311  RZ_LOG_ERROR("FLIRT: expecting tail byte at line %u but got (%s)\n", line_num, tmp_tok + i);
312  goto err;
313  }
314  ut8 byte = parse_byte(tmp_tok[i], tmp_tok[i + 1]);
315 
317  if (!tail || !rz_list_append(module->tail_bytes, tail)) {
318  free(tail);
319  RZ_LOG_ERROR("FLIRT: cannot allocate or append RzFlirtTailByte\n");
320  goto err;
321  }
322 
323  tail->offset = o;
324  tail->value = byte;
325  }
326  pat_dbg("tail: %s\n", tmp_tok);
327  }
328 
329  if (rz_list_length(module->public_functions) < 1) {
330  RZ_LOG_ERROR("FLIRT: a node must have at least one public function\n");
331  goto err;
332  }
333 
334  if (!rz_list_append(root->child_list, child)) {
335  RZ_LOG_ERROR("FLIRT: cannot append child to root\n");
336  goto err;
337  }
338 
339  rz_list_free(tokens);
340  return true;
341 
342 err:
344  rz_list_free(tokens);
345  return false;
346 }
347 
357  rz_return_val_if_fail(flirt_buf, NULL);
358 
359  if (optimization > RZ_FLIRT_NODE_OPTIMIZE_MAX) {
360  RZ_LOG_ERROR("FLIRT: optimization value is invalid (%u > RZ_FLIRT_NODE_OPTIMIZE_MAX).\n", optimization);
361  return NULL;
362  }
363 
365  const char *buffer_end = buffer + sizeof(buffer);
366  ut32 line_num = 1;
367  char *newline = NULL;
368  st64 read = 0;
369  RzFlirtNode *root = NULL;
370  RzStrBuf *line = NULL;
371 
373  if (!root) {
374  RZ_LOG_ERROR("FLIRT: cannot allocate root node\n");
375  return NULL;
376  }
377 
379  if (!root->child_list) {
380  free(root);
381  RZ_LOG_ERROR("FLIRT: cannot allocate root node child list\n");
382  return NULL;
383  }
384 
385  line = rz_strbuf_new("");
386  if (!line) {
388  RZ_LOG_ERROR("FLIRT: cannot allocate line buffer\n");
389  return NULL;
390  }
391 
392  bool tail_bytes = optimization != RZ_FLIRT_NODE_OPTIMIZE_MAX;
393  do {
394  if (newline && rz_strbuf_length(line) > 0) {
395  char *p = newline + 1;
396  pat_dbg("%05u: %s\n", line_num, rz_strbuf_get(line));
397  bool parsed = flirt_pat_parse_line(root, line, line_num, tail_bytes);
400  if (!parsed) {
401  break;
402  }
403  line_num++;
404  if (p < buffer_end && *p) {
405  if ((newline = strchr(p, '\n'))) {
406  newline[0] = 0;
407  }
409  }
410  continue;
411  }
412  memset(buffer, 0, sizeof(buffer));
413  if ((read = rz_buf_read(flirt_buf, (ut8 *)buffer, sizeof(buffer) - 1)) < 1) {
414  break;
415  }
416  if ((newline = strchr(buffer, '\n'))) {
417  newline[0] = 0;
418  }
420  } while (true);
421 
422  if (rz_strbuf_length(line) > 0) {
423  flirt_pat_parse_line(root, line, line_num, tail_bytes);
424  }
425 
427 
428  if (optimization == RZ_FLIRT_NODE_OPTIMIZE_NONE) {
430  } else if (!flirt_node_optimize(root)) {
432  return NULL;
433  }
434 
435  if (info) {
437  info->u.pat.n_modules = rz_sign_flirt_node_count_nodes(root);
438  }
439 
440  return root;
441 }
442 
443 static void flirt_pat_append_prelude(RzStrBuf *prelude, RZ_NONNULL const RzFlirtNode *child) {
444  for (ut32 i = 0; i < child->length; i++) {
445  if (child->pattern_mask[i]) {
446  rz_strbuf_appendf(prelude, "%02X", child->pattern_bytes[i]);
447  } else {
448  rz_strbuf_append(prelude, "..");
449  }
450  }
451 }
452 
454  flirt_pat_append_prelude(prelude, node);
455  int prelude_len = rz_strbuf_length(prelude);
456 
457  if (rz_list_length(node->child_list) > 0) {
458  RzListIter *it;
459  RzFlirtNode *child;
460  rz_list_foreach (node->child_list, it, child) {
461  rz_strbuf_slice(prelude, 0, prelude_len);
462  if (!flirt_pat_write_line(child, buffer, prelude)) {
463  return false;
464  }
465  }
466  return true;
467  }
468 
469  if (prelude_len < (RZ_FLIRT_MAX_PRELUDE_SIZE << 1)) {
470  const char *pad = rz_str_pad('.', (RZ_FLIRT_MAX_PRELUDE_SIZE << 1) - prelude_len);
471  rz_strbuf_append(prelude, pad);
472  }
473 
474  char tmp[32];
475  ut32 offset = 0;
476  RzListIter *it, *it2;
477  const RzFlirtModule *module;
478  const RzFlirtFunction *function;
479  const RzFlirtTailByte *byte;
480  rz_list_foreach (node->module_list, it, module) {
481  // prelude pattern mask
483 
484  // crc16 length + crc16 value
485  rz_strf(tmp, " %02X %04X ", module->crc_length, module->crc16);
487 
488  // function size
489  rz_strf(tmp, "%04X ", module->length);
491  // public functions
492  rz_list_foreach (module->public_functions, it2, function) {
493  rz_strf(tmp, ":%04X%s ", function->offset, function->is_local ? "@" : "");
495  rz_buf_append_string(buffer, function->name);
497  }
498  // referenced functions
499  rz_list_foreach (module->referenced_functions, it2, function) {
500  rz_strf(tmp, "^%04X ", function->offset);
502  rz_buf_append_string(buffer, function->name);
504  }
505 
506  // tail bytes (if any)
507  offset = 0;
508  rz_list_foreach (module->tail_bytes, it2, byte) {
509  while (offset < byte->offset) {
511  offset++;
512  }
513  rz_strf(tmp, "%02X", byte->value);
515  offset++;
516  }
518  }
519  return true;
520 }
521 
530  rz_return_val_if_fail(root && buffer, false);
531  // 4154554889FD534889F3C60700E8........C6441DFF004189C485C07515BE2E 07 FAEE 003B :0000@ Curl_gethostname ^000E gethostname ^0027 strchr ........4885C07403C600004489E05B5D415CC3
532  RzStrBuf sb;
533 
534  RzListIter *it;
535  RzFlirtNode *child;
536  rz_list_foreach (root->child_list, it, child) {
537  rz_strbuf_init(&sb);
538  if (!flirt_pat_write_line(child, buffer, &sb)) {
539  return false;
540  }
541  rz_strbuf_fini(&sb);
542  }
543  rz_buf_append_string(buffer, "---\n");
544  return true;
545 }
#define mask()
lzma_index ** i
Definition: index.h:629
static bool err
Definition: armass.c:435
static ut8 bytes[32]
Definition: asm_arc.c:23
static SblHeader sb
Definition: bin_mbn.c:26
RzBinInfo * info(RzBinFile *bf)
Definition: bin_ne.c:86
struct buffer buffer
static int value
Definition: cmd_api.c:93
#define RZ_API
#define NULL
Definition: cris-opc.c:27
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
uint32_t ut32
int root
Definition: enough.c:226
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf uLong offset
Definition: ioapi.h:144
uint8_t ut8
Definition: lh5801.h:11
return memset(p, 0, total)
void * p
Definition: libc.cpp:67
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
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 RZ_OWN void * rz_list_pop_head(RZ_NONNULL RzList *list)
Removes and returns the first element of the list.
Definition: list.c:401
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
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
line
Definition: setup.py:34
RZ_API RZ_OWN RzFlirtNode * rz_sign_flirt_parse_string_pattern_from_buffer(RZ_NONNULL RzBuffer *flirt_buf, ut32 optimization, RZ_NULLABLE RzFlirtInfo *info)
Parses the RzBuffer containing a FLIRT signature in string format and returns an RzFlirtNode.
Definition: pat.c:356
#define PAT_LINE_BUFFER_SIZE
Definition: pat.c:52
int flirt_compare_node(const RzFlirtNode *a, const RzFlirtNode *b)
Definition: create.c:225
RZ_API bool rz_sign_flirt_write_string_pattern_to_buffer(RZ_NONNULL const RzFlirtNode *root, RZ_NONNULL RzBuffer *buffer)
Writes in the the RzBuffer the FLIRT signatures in string format.
Definition: pat.c:529
static bool flirt_pat_write_line(RZ_NONNULL const RzFlirtNode *node, RZ_NONNULL RzBuffer *buffer, RzStrBuf *prelude)
Definition: pat.c:453
void module_free(RzFlirtModule *module)
Definition: flirt.c:284
static ut8 decode_byte(char b)
Definition: pat.c:58
static bool flirt_pat_parse_line(RzFlirtNode *root, RzStrBuf *sb, ut32 line_num, bool tail_bytes)
Definition: pat.c:140
static void flirt_pat_append_prelude(RzStrBuf *prelude, RZ_NONNULL const RzFlirtNode *child)
Definition: pat.c:443
bool flirt_node_optimize(RzFlirtNode *root)
Definition: create.c:316
static bool flirt_pat_parse_pattern_mask(const char *in_pattern, RzFlirtNode *child)
Definition: pat.c:72
static ut8 parse_byte(char high, char low)
Definition: pat.c:67
#define pat_dbg(...)
Definition: pat.c:49
static void pad(RzStrBuf *sb, ut32 count)
Definition: protobuf.c:36
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
RZ_API st64 rz_buf_append_string(RZ_NONNULL RzBuffer *b, RZ_NONNULL const char *str)
Append a string to the buffer.
Definition: buf.c:962
RZ_API st64 rz_buf_read(RZ_NONNULL RzBuffer *b, RZ_NONNULL RZ_OUT ut8 *buf, ut64 len)
RZ_API void rz_sign_flirt_node_free(RZ_NULLABLE RzFlirtNode *node)
Frees an RzFlirtNode struct.
Definition: flirt.c:299
RZ_API ut32 rz_sign_flirt_node_count_nodes(RZ_NONNULL const RzFlirtNode *node)
Counts the number of FLIRT signatures in the node.
Definition: flirt.c:1334
#define RZ_FLIRT_MAX_PRELUDE_SIZE
Definition: rz_flirt.h:20
@ 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
@ RZ_FLIRT_FILE_TYPE_PAT
.pat text format pattern file
Definition: rz_flirt.h:194
#define RZ_FLIRT_NAME_MAX
Definition: rz_flirt.h:17
void(* RzListFree)(void *ptr)
Definition: rz_list.h:11
int(* RzListComparator)(const void *value, const void *list_data)
Definition: rz_list.h:33
#define RZ_LOG_WARN(fmtstr,...)
Definition: rz_log.h:56
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
#define RZ_STR_ISNOTEMPTY(x)
Definition: rz_str.h:68
#define RZ_STR_ISEMPTY(x)
Definition: rz_str.h:67
RZ_API const char * rz_str_pad(const char ch, int len)
Definition: str.c:3236
RZ_API RzList * rz_str_split_list(char *str, const char *c, int n)
Split the string str according to the substring c and returns a RzList with the result.
Definition: str.c:3429
#define rz_strf(buf,...)
Convenience macro for local temporary strings.
Definition: rz_str.h:59
#define IS_HEXCHAR(x)
Definition: rz_str_util.h:9
RZ_API char * rz_strbuf_get(RzStrBuf *sb)
Definition: strbuf.c:321
RZ_API bool rz_strbuf_slice(RZ_NONNULL RzStrBuf *sb, size_t from, size_t len)
Cuts the current string into a substring.
Definition: strbuf.c:122
RZ_API bool rz_strbuf_append(RzStrBuf *sb, const char *s)
Definition: strbuf.c:222
RZ_API void rz_strbuf_fini(RzStrBuf *sb)
Definition: strbuf.c:365
RZ_API RzStrBuf * rz_strbuf_new(const char *s)
Definition: strbuf.c:8
RZ_API void rz_strbuf_free(RzStrBuf *sb)
Definition: strbuf.c:358
RZ_API bool rz_strbuf_appendf(RzStrBuf *sb, const char *fmt,...) RZ_PRINTF_CHECK(2
RZ_API void rz_strbuf_init(RzStrBuf *sb)
Definition: strbuf.c:33
RZ_API int rz_strbuf_length(RzStrBuf *sb)
Definition: strbuf.c:28
#define RZ_NEWS(x, y)
Definition: rz_types.h:283
#define RZ_NULLABLE
Definition: rz_types.h:65
#define RZ_OWN
Definition: rz_types.h:62
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define RZ_NONNULL
Definition: rz_types.h:64
#define RZ_MIN(x, y)
#define st64
Definition: rz_types_base.h:10
#define b(i)
Definition: sha256.c:42
#define a(i)
Definition: sha256.c:41
Definition: buffer.h:15
Definition: sftypes.h:77
char * type
Definition: rz_bin.h:211
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
int read(izstream &zs, T *x, Items items)
Definition: zstream.h:115