comparison tools/fanalyze.c @ 1682:2cfb4806cf71

Add simple and naively implemented multi-file bindiff type file analyzer utility 'fanalyze'.
author Matti Hamalainen <ccr@tnsp.org>
date Thu, 31 May 2018 15:15:50 +0300
parents
children 187a9f3c9e88
comparison
equal deleted inserted replaced
1681:bd68c9adc7ca 1682:2cfb4806cf71
1 /*
2 * Fanalyze - Analyze similarities between multiple files
3 * Programmed and designed by Matti 'ccr' Hamalainen
4 * (C) Copyright 2018 Tecnic Software productions (TNSP)
5 *
6 * Please read file 'COPYING' for information on license and distribution.
7 */
8 #include "dmtool.h"
9 #include "dmlib.h"
10 #include "dmargs.h"
11 #include "dmfile.h"
12
13 #define SET_MAX_FILES (8)
14
15
16 /* Typedefs
17 */
18 typedef struct
19 {
20 char *filename;
21 Uint8 *data;
22 size_t size; // offset, crop_start, crop_end, doCrop?
23 } DMSourceFile;
24
25
26 /* Global variables
27 */
28 int nsrcFiles = 0; // Number of source files
29 DMSourceFile srcFiles[SET_MAX_FILES]; // Source file names
30
31
32 /* Arguments
33 */
34 static const DMOptArg optList[] =
35 {
36 { 0, '?', "help", "Show this help", OPT_NONE },
37 { 1, 'v', "verbose", "Be more verbose", OPT_NONE },
38 };
39
40 static const int optListN = sizeof(optList) / sizeof(optList[0]);
41
42
43 void argShowHelp()
44 {
45 dmPrintBanner(stdout, dmProgName, "[options] <input file #1> <input file #2> [...]");
46 dmArgsPrintHelp(stdout, optList, optListN, 0);
47 }
48
49
50 BOOL argHandleOpt(const int optN, char *optArg, char *currArg)
51 {
52 switch (optN)
53 {
54 case 0:
55 argShowHelp();
56 exit(0);
57 break;
58
59 case 1:
60 dmVerbosity++;
61 break;
62
63 default:
64 dmErrorMsg("Unknown argument '%s'.\n", currArg);
65 return FALSE;
66 }
67
68 return TRUE;
69 }
70
71
72 BOOL argHandleNonOpt(char *currArg)
73 {
74 if (nsrcFiles < SET_MAX_FILES)
75 {
76 DMSourceFile *file = &srcFiles[nsrcFiles++];
77 file->filename = currArg;
78 return TRUE;
79 }
80 else
81 {
82 dmErrorMsg("Maximum number of input files exceeded (%d).\n",
83 SET_MAX_FILES);
84 return FALSE;
85 }
86 }
87
88
89 #define SET_MAX_ELEMS 256
90 typedef struct
91 {
92 Uint8 counts[SET_MAX_ELEMS];
93 Uint8 variants, data;
94 } DMCompElem;
95
96
97 int main(int argc, char *argv[])
98 {
99 DMCompElem *compBuf = NULL;
100 size_t compBufSize = 0;
101 int res;
102
103 dmInitProg("fanalyze", "File format analyzer", "0.1", NULL, NULL);
104 dmVerbosity = 1;
105
106 // Parse arguments
107 if (!dmArgsProcess(argc, argv, optList, optListN,
108 argHandleOpt, argHandleNonOpt, OPTH_BAILOUT))
109 exit(1);
110
111 if (nsrcFiles < 1)
112 {
113 dmErrorMsg("Nothing to do. (try --help)\n");
114 goto out;
115 }
116
117 // Read input files
118 for (int nfile = 0; nfile < nsrcFiles; nfile++)
119 {
120 DMSourceFile *file = &srcFiles[nfile];
121 dmPrint(2, "Input #%d: %s\n", nfile + 1, file->filename);
122 if ((res = dmReadDataFile(NULL, file->filename, &file->data, &file->size)) != DMERR_OK)
123 {
124 dmErrorMsg("Could not read '%s': %s\n",
125 file->filename, dmErrorStr(res));
126 goto out;
127 }
128
129 if (file->size > compBufSize)
130 compBufSize = file->size;
131 }
132
133 // Allocate comparision buffer
134 // XXX: integer overflow?
135 dmPrint(2, "Allocating %d element (%d bytes) comparision buffer.\n",
136 compBufSize, compBufSize * sizeof(DMCompElem));
137
138 if ((compBuf = dmCalloc(compBufSize, sizeof(DMCompElem))) == NULL)
139 {
140 dmErrorMsg("Out of memory. Could not allocate comparision buffer!\n");
141 goto out;
142 }
143
144 // Begin analyzing ..
145 dmPrint(2, "Analyzing ..\n");
146 for (int nfile = 0; nfile < nsrcFiles; nfile++)
147 {
148 DMSourceFile *file = &srcFiles[nfile];
149 for (size_t offs = 0; offs < compBufSize; offs++)
150 if (offs < file->size)
151 compBuf[offs].counts[file->data[offs]]++;
152 else
153 compBuf[offs].counts[0]++;
154 }
155
156 for (size_t offs = 0; offs < compBufSize; offs++)
157 {
158 DMCompElem *el = &compBuf[offs];
159 for (int n = 0; n < SET_MAX_ELEMS; n++)
160 {
161 if (el->counts[n] > 0)
162 {
163 el->variants++;
164 el->data = n;
165 }
166 }
167 }
168
169 // Display results
170 for (size_t offs = 0, n = 0; offs < compBufSize; offs++)
171 {
172 DMCompElem *el = &compBuf[offs];
173 BOOL var = el->variants > 1;
174
175 if (n == 0)
176 printf("%08x | ", offs);
177
178 if (var)
179 printf("[%2d] ", el->variants);
180 else
181 printf(" %02x ", el->data);
182
183 if (++n >= 16)
184 {
185 printf("\n");
186 n = 0;
187 }
188 }
189
190 printf("\n");
191
192 out:
193 for (int nfile = 0; nfile < nsrcFiles; nfile++)
194 {
195 DMSourceFile *file = &srcFiles[nfile];
196 dmFree(file->data);
197 }
198
199 return 0;
200 }