Mercurial > hg > dmlib
comparison tools/fanalyze.c @ 2586:9807ae37ad69
Require stdbool.h, we require C11 now.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Thu, 08 Dec 2022 15:59:22 +0200 |
parents | 9f26a93d7e70 |
children | 81f45b2fa118 |
comparison
equal
deleted
inserted
replaced
2585:ef6c826c5b7a | 2586:9807ae37ad69 |
---|---|
49 { | 49 { |
50 char *filename; | 50 char *filename; |
51 Uint8 *data; | 51 Uint8 *data; |
52 size_t size; | 52 size_t size; |
53 DMStats stats; | 53 DMStats stats; |
54 BOOL analyzed; | 54 bool analyzed; |
55 size_t index; | 55 size_t index; |
56 } DMSourceFile; | 56 } DMSourceFile; |
57 | 57 |
58 | 58 |
59 typedef struct | 59 typedef struct |
98 { | 98 { |
99 int type; | 99 int type; |
100 int disp; | 100 int disp; |
101 int nvalues; | 101 int nvalues; |
102 Uint32 values[SET_MAX_GREP_LIST]; | 102 Uint32 values[SET_MAX_GREP_LIST]; |
103 BOOL vwildcards[SET_MAX_GREP_LIST]; | 103 bool vwildcards[SET_MAX_GREP_LIST]; |
104 } DMGrepValue; | 104 } DMGrepValue; |
105 | 105 |
106 | 106 |
107 typedef struct | 107 typedef struct |
108 { | 108 { |
154 DMSourceFile srcFiles[SET_MAX_FILES]; // Source file names | 154 DMSourceFile srcFiles[SET_MAX_FILES]; // Source file names |
155 DMStats totalStats; | 155 DMStats totalStats; |
156 int nsetGrepValues = 0; | 156 int nsetGrepValues = 0; |
157 DMGrepValue setGrepValues[SET_MAX_GREP_VALUES]; | 157 DMGrepValue setGrepValues[SET_MAX_GREP_VALUES]; |
158 size_t optMinMatchLen = 8; | 158 size_t optMinMatchLen = 8; |
159 BOOL optOffsetMode = FALSE; | 159 bool optOffsetMode = false; |
160 | 160 |
161 DMMatchSeq dmSequences[SET_MAX_SEQUENCES]; | 161 DMMatchSeq dmSequences[SET_MAX_SEQUENCES]; |
162 int ndmSequences = 0; | 162 int ndmSequences = 0; |
163 | 163 |
164 | 164 |
202 "under development.\n" | 202 "under development.\n" |
203 ); | 203 ); |
204 } | 204 } |
205 | 205 |
206 | 206 |
207 BOOL dmGetData(const int type, const DMSourceFile *file, const size_t offs, Uint32 *mval) | 207 bool dmGetData(const int type, const DMSourceFile *file, const size_t offs, Uint32 *mval) |
208 { | 208 { |
209 Uint8 *data = file->data + offs; | 209 Uint8 *data = file->data + offs; |
210 if (offs + dmGrepTypes[type].bsize >= file->size) | 210 if (offs + dmGrepTypes[type].bsize >= file->size) |
211 { | 211 { |
212 *mval = 0; | 212 *mval = 0; |
213 return FALSE; | 213 return false; |
214 } | 214 } |
215 | 215 |
216 switch (type) | 216 switch (type) |
217 { | 217 { |
218 case DMGV_UINT8: | 218 case DMGV_UINT8: |
235 *mval = DM_BE32_TO_NATIVE(*((Uint32 *) data)); | 235 *mval = DM_BE32_TO_NATIVE(*((Uint32 *) data)); |
236 break; | 236 break; |
237 | 237 |
238 default: | 238 default: |
239 *mval = 0; | 239 *mval = 0; |
240 return FALSE; | 240 return false; |
241 } | 241 } |
242 return TRUE; | 242 return true; |
243 } | 243 } |
244 | 244 |
245 | 245 |
246 void dmPrintGrepValueList(FILE *fh, const DMGrepValue *node, const BOOL match, DMSourceFile *file, const size_t offs) | 246 void dmPrintGrepValueList(FILE *fh, const DMGrepValue *node, const bool match, DMSourceFile *file, const size_t offs) |
247 { | 247 { |
248 char mfmt[16]; | 248 char mfmt[16]; |
249 unsigned int bsize = dmGrepTypes[node->type].bsize; | 249 unsigned int bsize = dmGrepTypes[node->type].bsize; |
250 | 250 |
251 snprintf(mfmt, sizeof(mfmt), "%%%s%d%s%%s", | 251 snprintf(mfmt, sizeof(mfmt), "%%%s%d%s%%s", |
278 { | 278 { |
279 const char *specsep = strchr(arg, ':'); | 279 const char *specsep = strchr(arg, ':'); |
280 char *vspec, *vstr, *vsep; | 280 char *vspec, *vstr, *vsep; |
281 DMGrepValue val; | 281 DMGrepValue val; |
282 int ret = DMERR_OK; | 282 int ret = DMERR_OK; |
283 BOOL more; | 283 bool more; |
284 | 284 |
285 memset(&val, 0, sizeof(val)); | 285 memset(&val, 0, sizeof(val)); |
286 | 286 |
287 if (setMode != FA_ANALYZE && setMode != mode) | 287 if (setMode != FA_ANALYZE && setMode != mode) |
288 { | 288 { |
304 } | 304 } |
305 | 305 |
306 // Parse spec if any | 306 // Parse spec if any |
307 if (vspec != NULL) | 307 if (vspec != NULL) |
308 { | 308 { |
309 BOOL vendianess = TRUE; | 309 bool vendianess = true; |
310 char *vtmp = vspec; | 310 char *vtmp = vspec; |
311 | 311 |
312 // Get endianess specifier, if any | 312 // Get endianess specifier, if any |
313 if (strncasecmp(vtmp, "le", 2) == 0) | 313 if (strncasecmp(vtmp, "le", 2) == 0) |
314 { | 314 { |
315 vendianess = TRUE; | 315 vendianess = true; |
316 vtmp += 2; | 316 vtmp += 2; |
317 } | 317 } |
318 else | 318 else |
319 if (strncasecmp(vtmp, "be", 2) == 0) | 319 if (strncasecmp(vtmp, "be", 2) == 0) |
320 { | 320 { |
321 vendianess = FALSE; | 321 vendianess = false; |
322 vtmp += 2; | 322 vtmp += 2; |
323 } | 323 } |
324 | 324 |
325 // Get value bit size | 325 // Get value bit size |
326 if (strncmp(vtmp, "8", 1) == 0) | 326 if (strncmp(vtmp, "8", 1) == 0) |
382 } | 382 } |
383 | 383 |
384 if ((vsep = strchr(vtmp, ',')) != NULL) | 384 if ((vsep = strchr(vtmp, ',')) != NULL) |
385 { | 385 { |
386 *vsep = 0; | 386 *vsep = 0; |
387 more = TRUE; | 387 more = true; |
388 } | 388 } |
389 else | 389 else |
390 more = FALSE; | 390 more = false; |
391 | 391 |
392 if (vtmp[0] == '#' || vtmp[0] == '?') | 392 if (vtmp[0] == '#' || vtmp[0] == '?') |
393 { | 393 { |
394 val.vwildcards[val.nvalues] = TRUE; | 394 val.vwildcards[val.nvalues] = true; |
395 if (mode == FA_OFFSET) | 395 if (mode == FA_OFFSET) |
396 { | 396 { |
397 ret = dmError(DMERR_INVALID_ARGS, | 397 ret = dmError(DMERR_INVALID_ARGS, |
398 "Offset mode does not allow wildcard values.\n"); | 398 "Offset mode does not allow wildcard values.\n"); |
399 goto out; | 399 goto out; |
469 if (mode == FA_GREP) | 469 if (mode == FA_GREP) |
470 { | 470 { |
471 printf("Grep %s: ", | 471 printf("Grep %s: ", |
472 dmGrepTypes[val.type].desc); | 472 dmGrepTypes[val.type].desc); |
473 | 473 |
474 dmPrintGrepValueList(stdout, node, FALSE, NULL, 0); | 474 dmPrintGrepValueList(stdout, node, false, NULL, 0); |
475 printf("\n"); | 475 printf("\n"); |
476 } | 476 } |
477 } | 477 } |
478 else | 478 else |
479 { | 479 { |
487 dmFree(vstr); | 487 dmFree(vstr); |
488 return ret; | 488 return ret; |
489 } | 489 } |
490 | 490 |
491 | 491 |
492 BOOL argHandleOpt(const int optN, char *optArg, char *currArg) | 492 bool argHandleOpt(const int optN, char *optArg, char *currArg) |
493 { | 493 { |
494 switch (optN) | 494 switch (optN) |
495 { | 495 { |
496 case 0: | 496 case 0: |
497 argShowHelp(); | 497 argShowHelp(); |
521 optMinMatchLen = atoi(optArg); | 521 optMinMatchLen = atoi(optArg); |
522 if (optMinMatchLen < 2 || optMinMatchLen > 16*1024) | 522 if (optMinMatchLen < 2 || optMinMatchLen > 16*1024) |
523 { | 523 { |
524 dmErrorMsg("Invalid minimum match length '%s'.\n", | 524 dmErrorMsg("Invalid minimum match length '%s'.\n", |
525 optArg); | 525 optArg); |
526 return FALSE; | 526 return false; |
527 } | 527 } |
528 return TRUE; | 528 return true; |
529 | 529 |
530 case 18: | 530 case 18: |
531 optOffsetMode = TRUE; | 531 optOffsetMode = true; |
532 break; | 532 break; |
533 | 533 |
534 default: | 534 default: |
535 dmErrorMsg("Unknown argument '%s'.\n", currArg); | 535 dmErrorMsg("Unknown argument '%s'.\n", currArg); |
536 return FALSE; | 536 return false; |
537 } | 537 } |
538 | 538 |
539 return TRUE; | 539 return true; |
540 } | 540 } |
541 | 541 |
542 | 542 |
543 BOOL argHandleNonOpt(char *currArg) | 543 bool argHandleNonOpt(char *currArg) |
544 { | 544 { |
545 if (nsrcFiles < SET_MAX_FILES) | 545 if (nsrcFiles < SET_MAX_FILES) |
546 { | 546 { |
547 DMSourceFile *file = &srcFiles[nsrcFiles]; | 547 DMSourceFile *file = &srcFiles[nsrcFiles]; |
548 file->filename = currArg; | 548 file->filename = currArg; |
549 file->index = nsrcFiles; | 549 file->index = nsrcFiles; |
550 nsrcFiles++; | 550 nsrcFiles++; |
551 return TRUE; | 551 return true; |
552 } | 552 } |
553 else | 553 else |
554 { | 554 { |
555 dmErrorMsg("Maximum number of input files exceeded (%d).\n", | 555 dmErrorMsg("Maximum number of input files exceeded (%d).\n", |
556 SET_MAX_FILES); | 556 SET_MAX_FILES); |
557 return TRUE; | 557 return true; |
558 } | 558 } |
559 } | 559 } |
560 | 560 |
561 | 561 |
562 void dmInitStats(DMStats *stats) | 562 void dmInitStats(DMStats *stats) |
589 } | 589 } |
590 printf("\n\n"); | 590 printf("\n\n"); |
591 } | 591 } |
592 | 592 |
593 | 593 |
594 BOOL dmAddMatchSequence(Uint8 *data, const size_t len, DMSourceFile *file, size_t offs) | 594 bool dmAddMatchSequence(Uint8 *data, const size_t len, DMSourceFile *file, size_t offs) |
595 { | 595 { |
596 DMMatchSeq *seq = NULL; | 596 DMMatchSeq *seq = NULL; |
597 | 597 |
598 // Check for existing match sequence | 598 // Check for existing match sequence |
599 for (int n = 0; n < ndmSequences; n++) | 599 for (int n = 0; n < ndmSequences; n++) |
611 { | 611 { |
612 // No sequence found, add a new one | 612 // No sequence found, add a new one |
613 if (ndmSequences + 1 >= SET_MAX_SEQUENCES) | 613 if (ndmSequences + 1 >= SET_MAX_SEQUENCES) |
614 { | 614 { |
615 dmErrorMsg("Too many matching sequences found.\n"); | 615 dmErrorMsg("Too many matching sequences found.\n"); |
616 return FALSE; | 616 return false; |
617 } | 617 } |
618 | 618 |
619 seq = &dmSequences[ndmSequences++]; | 619 seq = &dmSequences[ndmSequences++]; |
620 } | 620 } |
621 else | 621 else |
624 for (int n = 0; n < seq->nplaces; n++) | 624 for (int n = 0; n < seq->nplaces; n++) |
625 { | 625 { |
626 DMMatchPlace *place = &seq->places[n]; | 626 DMMatchPlace *place = &seq->places[n]; |
627 if (place->file == file && | 627 if (place->file == file && |
628 place->offs + seq->len == offs + len) | 628 place->offs + seq->len == offs + len) |
629 return TRUE; | 629 return true; |
630 } | 630 } |
631 } | 631 } |
632 | 632 |
633 seq->data = data; | 633 seq->data = data; |
634 seq->len = len; | 634 seq->len = len; |
638 { | 638 { |
639 DMMatchPlace *place = &seq->places[seq->nplaces++]; | 639 DMMatchPlace *place = &seq->places[seq->nplaces++]; |
640 place->file = file; | 640 place->file = file; |
641 place->offs = offs; | 641 place->offs = offs; |
642 | 642 |
643 return TRUE; | 643 return true; |
644 } | 644 } |
645 else | 645 else |
646 return FALSE; | 646 return false; |
647 } | 647 } |
648 | 648 |
649 | 649 |
650 int dmCompareMatchPlaces(const void *pa, const void *pb) | 650 int dmCompareMatchPlaces(const void *pa, const void *pb) |
651 { | 651 { |
658 | 658 |
659 int main(int argc, char *argv[]) | 659 int main(int argc, char *argv[]) |
660 { | 660 { |
661 DMCompElem *compBuf = NULL; | 661 DMCompElem *compBuf = NULL; |
662 size_t compBufSize = 0, totalSize = 0, fileFlagsSize; | 662 size_t compBufSize = 0, totalSize = 0, fileFlagsSize; |
663 BOOL *fileFlags = NULL; | 663 bool *fileFlags = NULL; |
664 int res; | 664 int res; |
665 | 665 |
666 memset(&dmSequences, 0, sizeof(dmSequences)); | 666 memset(&dmSequences, 0, sizeof(dmSequences)); |
667 | 667 |
668 dmInitProg("fanalyze", | 668 dmInitProg("fanalyze", |
684 "No input file(s) specified.\n"); | 684 "No input file(s) specified.\n"); |
685 goto out; | 685 goto out; |
686 } | 686 } |
687 | 687 |
688 // Allocate file flags | 688 // Allocate file flags |
689 fileFlagsSize = sizeof(BOOL) * nsrcFiles; | 689 fileFlagsSize = sizeof(bool) * nsrcFiles; |
690 if ((fileFlags = dmMalloc(fileFlagsSize)) == NULL) | 690 if ((fileFlags = dmMalloc(fileFlagsSize)) == NULL) |
691 { | 691 { |
692 dmErrorMsg("Could not allocate %" DM_PRIu_SIZE_T " bytes of memory for file flag array.\n", | 692 dmErrorMsg("Could not allocate %" DM_PRIu_SIZE_T " bytes of memory for file flag array.\n", |
693 fileFlagsSize); | 693 fileFlagsSize); |
694 goto out; | 694 goto out; |
728 | 728 |
729 for (int n = 0; n < nsetGrepValues; n++) | 729 for (int n = 0; n < nsetGrepValues; n++) |
730 { | 730 { |
731 DMGrepValue *node = &setGrepValues[n]; | 731 DMGrepValue *node = &setGrepValues[n]; |
732 const DMGrepType *def = &dmGrepTypes[node->type]; | 732 const DMGrepType *def = &dmGrepTypes[node->type]; |
733 BOOL sep = FALSE; | 733 bool sep = false; |
734 | 734 |
735 if (optOffsetMode) | 735 if (optOffsetMode) |
736 { | 736 { |
737 printf("%s %s -o ", | 737 printf("%s %s -o ", |
738 argv[0], file->filename); | 738 argv[0], file->filename); |
739 } | 739 } |
740 | 740 |
741 for (size_t offs = 0; offs + (def->bsize * node->nvalues) < file->size; offs++) | 741 for (size_t offs = 0; offs + (def->bsize * node->nvalues) < file->size; offs++) |
742 { | 742 { |
743 BOOL match = TRUE; | 743 bool match = true; |
744 for (int n = 0; n < node->nvalues; n++) | 744 for (int n = 0; n < node->nvalues; n++) |
745 if (!node->vwildcards[n]) | 745 if (!node->vwildcards[n]) |
746 { | 746 { |
747 Uint32 mval; | 747 Uint32 mval; |
748 dmGetData(node->type, file, offs + n * def->bsize, &mval); | 748 dmGetData(node->type, file, offs + n * def->bsize, &mval); |
749 | 749 |
750 if (mval != node->values[n]) | 750 if (mval != node->values[n]) |
751 { | 751 { |
752 match = FALSE; | 752 match = false; |
753 break; | 753 break; |
754 } | 754 } |
755 } | 755 } |
756 | 756 |
757 if (match) | 757 if (match) |
758 { | 758 { |
759 if (optOffsetMode) | 759 if (optOffsetMode) |
760 { | 760 { |
761 printf("%s0x%" DM_PRIx_SIZE_T, sep ? "," : "", offs); | 761 printf("%s0x%" DM_PRIx_SIZE_T, sep ? "," : "", offs); |
762 sep = TRUE; | 762 sep = true; |
763 } | 763 } |
764 else | 764 else |
765 printf("%08" DM_PRIx_SIZE_T, offs); | 765 printf("%08" DM_PRIx_SIZE_T, offs); |
766 | 766 |
767 if (!optOffsetMode) | 767 if (!optOffsetMode) |
768 { | 768 { |
769 if (dmVerbosity >= 1) | 769 if (dmVerbosity >= 1) |
770 { | 770 { |
771 printf(" : "); | 771 printf(" : "); |
772 dmPrintGrepValueList(stdout, node, TRUE, file, offs); | 772 dmPrintGrepValueList(stdout, node, true, file, offs); |
773 } | 773 } |
774 printf("\n"); | 774 printf("\n"); |
775 } | 775 } |
776 } | 776 } |
777 } | 777 } |
900 // Display results | 900 // Display results |
901 // | 901 // |
902 for (size_t offs = 0, n = 0; offs < compBufSize; offs++) | 902 for (size_t offs = 0, n = 0; offs < compBufSize; offs++) |
903 { | 903 { |
904 DMCompElem *el = &compBuf[offs]; | 904 DMCompElem *el = &compBuf[offs]; |
905 BOOL var = el->variants > 1; | 905 bool var = el->variants > 1; |
906 | 906 |
907 if (n == 0) | 907 if (n == 0) |
908 printf("%08" DM_PRIx_SIZE_T " | ", offs); | 908 printf("%08" DM_PRIx_SIZE_T " | ", offs); |
909 | 909 |
910 if (var) | 910 if (var) |
983 if (setMode == FA_DIFF) | 983 if (setMode == FA_DIFF) |
984 { | 984 { |
985 // | 985 // |
986 // Attempt to find matching sequences of N+ | 986 // Attempt to find matching sequences of N+ |
987 // | 987 // |
988 BOOL slow = FALSE; | 988 bool slow = false; |
989 int ss = 0; | 989 int ss = 0; |
990 printf("Attempting to find matching sequences of %" DM_PRIu_SIZE_T " bytes or more.\n", | 990 printf("Attempting to find matching sequences of %" DM_PRIu_SIZE_T " bytes or more.\n", |
991 optMinMatchLen); | 991 optMinMatchLen); |
992 | 992 |
993 if (totalSize > 32*1024) | 993 if (totalSize > 32*1024) |
994 { | 994 { |
995 dmPrint(0, | 995 dmPrint(0, |
996 "WARNING! Total data size is large, and the matching \"algorithm\"\n" | 996 "WARNING! Total data size is large, and the matching \"algorithm\"\n" |
997 "used is horribly inefficient. This will be quite slow ...\n"); | 997 "used is horribly inefficient. This will be quite slow ...\n"); |
998 slow = TRUE; | 998 slow = true; |
999 } | 999 } |
1000 | 1000 |
1001 for (int nfile1 = 0; nfile1 < nsrcFiles; nfile1++) | 1001 for (int nfile1 = 0; nfile1 < nsrcFiles; nfile1++) |
1002 { | 1002 { |
1003 DMSourceFile *file1 = &srcFiles[nfile1]; | 1003 DMSourceFile *file1 = &srcFiles[nfile1]; |
1040 | 1040 |
1041 if (cnt < optMinMatchLen) | 1041 if (cnt < optMinMatchLen) |
1042 moffs1++; | 1042 moffs1++; |
1043 } | 1043 } |
1044 } | 1044 } |
1045 file1->analyzed = TRUE; | 1045 file1->analyzed = true; |
1046 } | 1046 } |
1047 | 1047 |
1048 done: | 1048 done: |
1049 | 1049 |
1050 if (slow) | 1050 if (slow) |
1069 for (int nplace = 0; nplace < seq->nplaces; nplace++) | 1069 for (int nplace = 0; nplace < seq->nplaces; nplace++) |
1070 { | 1070 { |
1071 DMMatchPlace *place = &seq->places[nplace]; | 1071 DMMatchPlace *place = &seq->places[nplace]; |
1072 if (!fileFlags[place->file->index]) | 1072 if (!fileFlags[place->file->index]) |
1073 { | 1073 { |
1074 fileFlags[place->file->index] = TRUE; | 1074 fileFlags[place->file->index] = true; |
1075 seq->nfiles++; | 1075 seq->nfiles++; |
1076 } | 1076 } |
1077 } | 1077 } |
1078 } | 1078 } |
1079 | 1079 |