source: trunk/tools/finsig.c @ 1172

Revision 1172, 6.0 KB checked in by reyalP, 2 years ago (diff)

finsig optimization from philmoz in http://chdk.setepontos.com/index.php?topic=650.msg65911#msg65911

  • Property svn:eol-style set to native
Line 
1#include <stdlib.h>
2#include <stdio.h>
3#include <stdint.h>
4#include <string.h>
5#include <unistd.h>
6#include <time.h>
7
8#define MAX_MATCHES (64)
9
10typedef struct {
11    uint32_t ptr;
12    uint32_t fail;
13    uint32_t success;
14} Match;
15
16typedef struct {
17    uint32_t offs;
18    uint32_t value;
19    uint32_t mask;
20} FuncSig;
21
22typedef struct {
23    const char *name;
24    FuncSig *sig;
25} FuncsList;
26
27typedef struct bufrange {
28    uint32_t *p;
29    int off;
30    int len;
31    struct bufrange* next;
32} BufRange;
33
34BufRange *br, *last;
35
36void addBufRange(uint32_t *p, int o, int l)
37{
38    BufRange *n = malloc(sizeof(BufRange));
39    n->p = p;
40    n->off = o;
41    n->len = l;
42    n->next = 0;
43    if (br == 0)
44    {
45        br = n;
46    }
47    else
48    {
49        last->next = n;
50    }
51    last = n;
52}
53
54#if defined(PLATFORMOS_vxworks)
55#include "signatures_vxworks.h"
56#elif defined(PLATFORMOS_dryos)
57#include "signatures_dryos.h"
58#else
59#error Undefined platform OS
60#endif
61
62int match_compare(const Match *p1, const Match *p2)
63{
64    /* NOTE: If a function has *more* matches, it will be prefered, even if it has a lower percent matches */
65    if (p1->success > p2->success){
66        return -1;
67    } else
68        if (p1->success < p2->success){
69            return 1;
70        } else {
71            if (p1->fail < p2->fail){
72                return -1;
73            } else
74                if (p1->fail > p2->fail){
75                    return 1;
76                }
77        }
78
79        /* scores are equal. prefer lower address */
80
81        if (p1->ptr < p2->ptr){
82            return -1;
83        } else
84            if (p1->ptr > p2->ptr){
85                return 1;
86            }
87
88            return 0;
89}
90
91void usage()
92{
93    printf("finsig <primary> <base>\n");
94    exit(1);
95}
96
97int main(int argc, char **argv)
98{
99    Match matches[MAX_MATCHES];
100    uint32_t *buf, *p;
101    FILE *f;
102    int size;
103    int i,j,k;
104    int fail, success;
105    uint32_t base;
106    FuncSig *sig, *s;
107    int count;
108    int ret = 0;
109    const char *curr_name;
110    BufRange *n;
111
112    clock_t t1 = clock();
113
114    if (argc != 3)
115        usage();
116
117    f = fopen(argv[1], "r+b");
118
119    if (f == NULL)
120        usage();
121
122    base = strtoul(argv[2], NULL, 0);
123
124    printf("// !!! THIS FILE IS GENERATED. DO NOT EDIT. !!!\n");
125    printf("#include \"stubs_asm.h\"\n\n");
126
127    fseek(f,0,SEEK_END);
128    size=ftell(f)/4;
129    fseek(f,0,SEEK_SET);
130
131    // Max sig size if 32, add extra space at end of buffer and fill with 0xFFFFFFFF
132    // Allows sig matching past end of firmware without checking each time in the inner loop
133    buf=malloc((size+32)*4);
134    fread(buf, 4, size, f);
135    fclose(f);
136    memset(&buf[size],0xff,32*4);
137
138    // Find all the valid ranges for checking (skips over large blocks of 0xFFFFFFFF)
139    br = 0; last = 0;
140    k = -1; j = 0;
141    for (i = 0; i < size; i++)
142    {
143        if (buf[i] == 0xFFFFFFFF)   // Possible start of block to skip
144        {
145            if (k == -1)            // Mark start of possible skip block
146            {
147                k = i;
148            }
149        }
150        else                        // Found end of block ?
151        {
152            if (k != -1)
153            {
154                if (i - k > 32)     // If block more than 32 words then we want to skip it
155                {
156                    if (k - j > 8)
157                    {
158                        // Add a range record for the previous valid range (ignore short ranges)
159                        addBufRange(&buf[j],j,k - j);
160                    }
161                    j = i;          // Reset valid range start to current position
162                }
163                k = -1;             // Reset marker for skip block
164            }
165        }
166    }
167    // Add range for last valid block
168    if (k != -1)   
169    {
170        if (k - j > 8)
171        {
172            addBufRange(&buf[j],j,k - j);
173        }
174    }
175    else
176    {
177        if (i - j > 8)
178        {
179            addBufRange(&buf[j],j,i - j);
180        }
181    }
182
183    for (k = 0; func_list[k].name; k++){
184
185        count = 0;
186        curr_name = func_list[k].name;
187
188        while (1) {
189            sig = func_list[k].sig;
190
191            for (n = br; n != 0; n = n->next){
192                for (p = n->p, i = 0; i < n->len; p++, i++){
193                    fail = 0;
194                    success = 0;
195                    for (s = sig; s->offs != -1; s++){
196                        if ((p[s->offs] & s->mask) != s->value){
197                            fail++;
198                        } else {
199                            success++;
200                        }
201                    }
202                    if (success > fail){
203                        matches[count].ptr = base+((i+n->off)<<2);
204                        matches[count].success = success;
205                        matches[count].fail = fail;
206                        count ++;
207                        if (count >= MAX_MATCHES){
208                            printf("// WARNING: too many matches for %s!\n", func_list[k].name);
209                            break;
210                        }
211                    }
212                }
213            }
214
215            // same name, so we have another version of the same function
216            if ((func_list[k+1].name == NULL) || (strcmp(curr_name, func_list[k+1].name) != 0)) {
217                break;
218            }
219            k++;
220        }
221
222        // find best match and report results
223        if (count == 0){
224            printf("// ERROR: %s is not found!\n", curr_name);
225            ret = 1;
226        } else {
227            if (count > 1){
228                qsort(matches, count, sizeof(Match), (void*)match_compare);
229            }
230
231            if (matches->fail > 0)
232                printf("// Best match: %d%%\n", matches->success*100/(matches->success+matches->fail));
233
234            printf("NSTUB(%s, 0x%x)\n", curr_name, matches->ptr);
235
236            for (i=1;i<count && matches[i].fail==matches[0].fail;i++){
237                printf("// ALT: NSTUB(%s, 0x%x) // %d/%d\n", curr_name, matches[i].ptr, matches[i].success, matches[i].fail);
238            }
239        }
240    }
241
242    clock_t t2 = clock();
243
244    fprintf(stderr,"Time to generate stubs %.2f seconds\n",(double)(t2-t1)/(double)CLOCKS_PER_SEC);
245
246    return ret;
247}
248
Note: See TracBrowser for help on using the repository browser.