47 #define pat_dbg(...) eprintf(__VA_ARGS__)
52 #define PAT_LINE_BUFFER_SIZE 1024
59 if (
b >=
'0' &&
b <=
'9') {
61 }
else if (
b >=
'A' &&
b <=
'F') {
62 return (
b -
'A') + 10;
64 return (
b -
'a') + 10;
80 length = strlen(in_pattern);
100 for (
ut32 i = 0;
i < n_bytes; ++
i) {
103 char high = in_pattern[
p];
104 char low = in_pattern[
p + 1];
108 }
else if (high ==
'.' && low ==
'.') {
143 char *tmp_tok =
NULL;
147 if (!strncmp(
line,
"---", strlen(
"---"))) {
149 }
else if (
line[0] ==
'#') {
153 if (
line[line_len - 1] ==
'\r') {
156 if (*
line || line_len < 1) {
157 RZ_LOG_WARN(
"FLIRT: line %u is empty\n", line_num);
163 if (rz_list_empty(tokens)) {
164 RZ_LOG_ERROR(
"FLIRT: cannot tokenize line %u\n", line_num);
176 RZ_LOG_ERROR(
"FLIRT: cannot allocate child module list\n");
183 RZ_LOG_ERROR(
"FLIRT: cannot allocate or append child module\n");
188 if (!
module->public_functions) {
189 RZ_LOG_ERROR(
"FLIRT: cannot allocate child module public function list\n");
194 if (!
module->public_functions) {
195 RZ_LOG_ERROR(
"FLIRT: cannot allocate child module referenced function list\n");
204 RZ_LOG_ERROR(
"FLIRT: invalid pattern with mask (%s) at line %u\n", tmp_tok, line_num);
207 pat_dbg(
"pattern: %s\n", tmp_tok);
216 RZ_LOG_ERROR(
"FLIRT: invalid crc16 length (%s) at line %u\n", tmp_tok, line_num);
219 pat_dbg(
"crc16 length: %s\n", tmp_tok);
225 if (tmp_tok && strlen(tmp_tok) == 4 &&
231 RZ_LOG_ERROR(
"FLIRT: invalid crc16 value (%s) at line %u\n", tmp_tok, line_num);
234 pat_dbg(
"crc16: %s\n", tmp_tok);
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);
244 pat_dbg(
"function size: %s\n", tmp_tok);
251 ut32 len_tok = strlen(tmp_tok);
253 bool is_local =
false;
254 if (len_tok > 0 && !(len_tok & 1) && (
IS_HEXCHAR(tmp_tok[0]) || tmp_tok[0] ==
'.')) {
259 if (len_tok >= 6 && tmp_tok[0] ==
':' && tmp_tok[len_tok - 1] ==
'@') {
261 tmp_tok[len_tok - 1] = 0;
264 to_append =
module->public_functions;
265 tmp_tok[len_tok - 1] =
'@';
266 }
else if (len_tok >= 5 && tmp_tok[0] ==
':') {
269 to_append =
module->public_functions;
270 }
else if (len_tok == 5 && tmp_tok[0] ==
'^') {
273 to_append =
module->referenced_functions;
275 RZ_LOG_ERROR(
"FLIRT: invalid symbol offset (%.10s len %u) at line %u\n", tmp_tok, len_tok, line_num);
281 RZ_LOG_ERROR(
"FLIRT: empty symbol name at line %u\n", line_num);
284 len_tok = strlen(tmp_tok);
289 RZ_LOG_ERROR(
"FLIRT: cannot allocate or append RzFlirtFunction\n");
292 function->is_local = is_local;
293 function->offset =
offset;
295 pat_dbg(
"%s function: %04x %s\n", to_append ==
module->referenced_functions ?
"ref" : (function->is_local ?
"loc" :
"pub"),
offset, tmp_tok);
299 size_t len_tok = strlen(tmp_tok);
302 if (!
module->public_functions) {
303 RZ_LOG_ERROR(
"FLIRT: cannot allocate child module tail bytes list\n");
308 if (tmp_tok[
i] ==
'.' && tmp_tok[
i + 1] ==
'.') {
311 RZ_LOG_ERROR(
"FLIRT: expecting tail byte at line %u but got (%s)\n", line_num, tmp_tok +
i);
319 RZ_LOG_ERROR(
"FLIRT: cannot allocate or append RzFlirtTailByte\n");
326 pat_dbg(
"tail: %s\n", tmp_tok);
330 RZ_LOG_ERROR(
"FLIRT: a node must have at least one public function\n");
360 RZ_LOG_ERROR(
"FLIRT: optimization value is invalid (%u > RZ_FLIRT_NODE_OPTIMIZE_MAX).\n", optimization);
367 char *newline =
NULL;
379 if (!
root->child_list) {
381 RZ_LOG_ERROR(
"FLIRT: cannot allocate root node child list\n");
395 char *
p = newline + 1;
404 if (
p < buffer_end && *
p) {
405 if ((newline = strchr(
p,
'\n'))) {
416 if ((newline = strchr(
buffer,
'\n'))) {
444 for (
ut32 i = 0;
i < child->length;
i++) {
445 if (child->pattern_mask[
i]) {
460 rz_list_foreach (node->child_list, it, child) {
480 rz_list_foreach (node->module_list, it,
module) {
492 rz_list_foreach (
module->public_functions, it2,
function) {
493 rz_strf(
tmp,
":%04X%s ", function->offset, function->is_local ?
"@" :
"");
499 rz_list_foreach (
module->referenced_functions, it2,
function) {
508 rz_list_foreach (
module->tail_bytes, it2,
byte) {
536 rz_list_foreach (
root->child_list, it, child) {
RzBinInfo * info(RzBinFile *bf)
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
RZ_API void Ht_() free(HtName_(Ht) *ht)
return memset(p, 0, total)
RZ_API RZ_OWN RzList * rz_list_newf(RzListFree f)
Returns a new initialized RzList pointer and sets the free method.
RZ_API void rz_list_sort(RZ_NONNULL RzList *list, RZ_NONNULL RzListComparator cmp)
Sorts via merge sort or via insertion sort a list.
RZ_API ut32 rz_list_length(RZ_NONNULL const RzList *list)
Returns the length of the list.
RZ_API RZ_OWN void * rz_list_pop_head(RZ_NONNULL RzList *list)
Removes and returns the first element of the list.
RZ_API RZ_BORROW RzListIter * rz_list_append(RZ_NONNULL RzList *list, void *data)
Appends at the end of the list a new element.
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
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.
#define PAT_LINE_BUFFER_SIZE
int flirt_compare_node(const RzFlirtNode *a, const RzFlirtNode *b)
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.
static bool flirt_pat_write_line(RZ_NONNULL const RzFlirtNode *node, RZ_NONNULL RzBuffer *buffer, RzStrBuf *prelude)
void module_free(RzFlirtModule *module)
static ut8 decode_byte(char b)
static bool flirt_pat_parse_line(RzFlirtNode *root, RzStrBuf *sb, ut32 line_num, bool tail_bytes)
static void flirt_pat_append_prelude(RzStrBuf *prelude, RZ_NONNULL const RzFlirtNode *child)
bool flirt_node_optimize(RzFlirtNode *root)
static bool flirt_pat_parse_pattern_mask(const char *in_pattern, RzFlirtNode *child)
static ut8 parse_byte(char high, char low)
static void pad(RzStrBuf *sb, ut32 count)
#define rz_return_val_if_fail(expr, val)
RZ_API st64 rz_buf_append_string(RZ_NONNULL RzBuffer *b, RZ_NONNULL const char *str)
Append a string to the buffer.
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.
RZ_API ut32 rz_sign_flirt_node_count_nodes(RZ_NONNULL const RzFlirtNode *node)
Counts the number of FLIRT signatures in the node.
#define RZ_FLIRT_MAX_PRELUDE_SIZE
@ RZ_FLIRT_NODE_OPTIMIZE_NONE
keeps the structure flattened (keep the tail bytes)
@ RZ_FLIRT_NODE_OPTIMIZE_MAX
optimize the tree structure and drops the tail bytes
@ RZ_FLIRT_FILE_TYPE_PAT
.pat text format pattern file
#define RZ_FLIRT_NAME_MAX
void(* RzListFree)(void *ptr)
int(* RzListComparator)(const void *value, const void *list_data)
#define RZ_LOG_WARN(fmtstr,...)
#define RZ_LOG_ERROR(fmtstr,...)
#define RZ_STR_ISNOTEMPTY(x)
#define RZ_STR_ISEMPTY(x)
RZ_API const char * rz_str_pad(const char ch, int len)
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.
#define rz_strf(buf,...)
Convenience macro for local temporary strings.
RZ_API char * rz_strbuf_get(RzStrBuf *sb)
RZ_API bool rz_strbuf_slice(RZ_NONNULL RzStrBuf *sb, size_t from, size_t len)
Cuts the current string into a substring.
RZ_API bool rz_strbuf_append(RzStrBuf *sb, const char *s)
RZ_API void rz_strbuf_fini(RzStrBuf *sb)
RZ_API RzStrBuf * rz_strbuf_new(const char *s)
RZ_API void rz_strbuf_free(RzStrBuf *sb)
RZ_API bool rz_strbuf_appendf(RzStrBuf *sb, const char *fmt,...) RZ_PRINTF_CHECK(2
RZ_API void rz_strbuf_init(RzStrBuf *sb)
RZ_API int rz_strbuf_length(RzStrBuf *sb)
int read(izstream &zs, T *x, Items items)