Changeset 1172


Ignore:
Timestamp:
05/04/11 06:25:13 (2 years ago)
Author:
reyalP
Message:

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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tools/finsig.c

    r1169 r1172  
    44#include <string.h> 
    55#include <unistd.h> 
     6#include <time.h> 
    67 
    78#define MAX_MATCHES (64) 
     
    2425} FuncsList; 
    2526 
     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 
    2654#if defined(PLATFORMOS_vxworks) 
    27   #include "signatures_vxworks.h" 
     55#include "signatures_vxworks.h" 
    2856#elif defined(PLATFORMOS_dryos) 
    29   #include "signatures_dryos.h" 
     57#include "signatures_dryos.h" 
    3058#else 
    31   #error Undefined platform OS 
     59#error Undefined platform OS 
    3260#endif 
    3361 
    3462int match_compare(const Match *p1, const Match *p2) 
    3563{ 
    36         /* NOTE: If a function has *more* matches, it will be prefered, even if it has a lower percent matches */ 
     64    /* NOTE: If a function has *more* matches, it will be prefered, even if it has a lower percent matches */ 
    3765    if (p1->success > p2->success){ 
    38         return -1; 
     66        return -1; 
    3967    } else 
    40     if (p1->success < p2->success){ 
    41         return 1; 
    42     } else { 
    43         if (p1->fail < p2->fail){ 
    44             return -1; 
    45         } else 
    46         if (p1->fail > p2->fail){ 
    47             return 1; 
    48         } 
    49     } 
    50  
    51     /* scores are equal. prefer lower address */ 
    52  
    53     if (p1->ptr < p2->ptr){ 
    54         return -1; 
    55     } else 
    56     if (p1->ptr > p2->ptr){ 
    57         return 1; 
    58     } 
    59  
    60     return 0; 
     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; 
    6189} 
    6290 
     
    7098{ 
    7199    Match matches[MAX_MATCHES]; 
    72     uint32_t *buf; 
     100    uint32_t *buf, *p; 
    73101    FILE *f; 
    74102    int size; 
     
    76104    int fail, success; 
    77105    uint32_t base; 
    78     FuncSig *sig; 
     106    FuncSig *sig, *s; 
    79107    int count; 
    80108    int ret = 0; 
    81109    const char *curr_name; 
     110    BufRange *n; 
     111 
     112    clock_t t1 = clock(); 
    82113 
    83114    if (argc != 3) 
    84         usage(); 
     115        usage(); 
    85116 
    86117    f = fopen(argv[1], "r+b"); 
    87118 
    88119    if (f == NULL) 
    89         usage(); 
     120        usage(); 
    90121 
    91122    base = strtoul(argv[2], NULL, 0); 
     
    98129    fseek(f,0,SEEK_SET); 
    99130 
    100     buf=malloc(size*4); 
     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); 
    101134    fread(buf, 4, size, f); 
    102  
    103     for (k=0;func_list[k].name;k++){ 
    104  
    105         count = 0; 
    106         curr_name = func_list[k].name; 
    107  
    108         while (1) { 
    109             sig = func_list[k].sig; 
    110  
    111             for (i=0;i<size;i++){ 
    112                 fail = 0; 
    113                 success = 0; 
    114                 for (j=0;sig[j].offs!=-1;j++){ 
    115                     if ((i+sig[j].offs) >= size || (buf[i+sig[j].offs] & sig[j].mask) != sig[j].value){ 
    116                         fail++; 
    117                     } else { 
    118                         success++; 
    119                     } 
    120                 } 
    121                 if (success > fail){ 
    122                     matches[count].ptr = base+i*4; 
    123                     matches[count].success = success; 
    124                     matches[count].fail = fail; 
    125                     count ++; 
    126                     if (count >= MAX_MATCHES){ 
    127                         printf("// WARNING: too many matches for %s!\n", func_list[k].name); 
    128                         break; 
    129                     } 
    130                 } 
    131             } 
    132  
    133             // same name, so we have another version of the same function 
    134             if ((func_list[k+1].name == NULL) || (strcmp(curr_name, func_list[k+1].name) != 0)) { 
    135                 break; 
    136             } 
    137             k++; 
    138         } 
    139  
    140         // find best match and report results 
    141         if (count == 0){ 
    142             printf("// ERROR: %s is not found!\n", curr_name); 
    143             ret = 1; 
    144         } else { 
    145             if (count > 1){ 
    146                 qsort(matches, count, sizeof(Match), (void*)match_compare); 
    147             } 
    148  
    149             if (matches->fail > 0) 
    150                 printf("// Best match: %d%%\n", matches->success*100/(matches->success+matches->fail)); 
    151  
    152             printf("NSTUB(%s, 0x%x)\n", curr_name, matches->ptr); 
    153  
    154             for (i=1;i<count && matches[i].fail==matches[0].fail;i++){ 
    155                 printf("// ALT: NSTUB(%s, 0x%x) // %d/%d\n", curr_name, matches[i].ptr, matches[i].success, matches[i].fail); 
    156             } 
    157         } 
    158     } 
     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); 
    159245 
    160246    return ret; 
Note: See TracChangeset for help on using the changeset viewer.