Changeset 1168


Ignore:
Timestamp:
05/03/11 04:43:27 (2 years ago)
Author:
reyalP
Message:

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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tools/finsig.c

    r817 r1168  
    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 len; 
     30    struct bufrange* next; 
     31} BufRange; 
     32 
     33BufRange *br, *last; 
     34 
     35void addBufRange(uint32_t *p, int l) 
     36{ 
     37    BufRange *n = malloc(sizeof(BufRange)); 
     38    n->p = p; 
     39    n->len = l; 
     40    n->next = 0; 
     41    if (br == 0) 
     42    { 
     43        br = n; 
     44    } 
     45    else 
     46    { 
     47        last->next = n; 
     48    } 
     49    last = n; 
     50} 
     51 
    2652#if defined(PLATFORMOS_vxworks) 
    27   #include "signatures_vxworks.h" 
     53#include "signatures_vxworks.h" 
    2854#elif defined(PLATFORMOS_dryos) 
    29   #include "signatures_dryos.h" 
     55#include "signatures_dryos.h" 
    3056#else 
    31   #error Undefined platform OS 
     57#error Undefined platform OS 
    3258#endif 
    3359 
    3460int match_compare(const Match *p1, const Match *p2) 
    3561{ 
    36         /* NOTE: If a function has *more* matches, it will be prefered, even if it has a lower percent matches */ 
     62    /* NOTE: If a function has *more* matches, it will be prefered, even if it has a lower percent matches */ 
    3763    if (p1->success > p2->success){ 
    38         return -1; 
     64        return -1; 
    3965    } 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; 
     66        if (p1->success < p2->success){ 
     67            return 1; 
     68        } else { 
     69            if (p1->fail < p2->fail){ 
     70                return -1; 
     71            } else 
     72                if (p1->fail > p2->fail){ 
     73                    return 1; 
     74                } 
     75        } 
     76 
     77        /* scores are equal. prefer lower address */ 
     78 
     79        if (p1->ptr < p2->ptr){ 
     80            return -1; 
     81        } else 
     82            if (p1->ptr > p2->ptr){ 
     83                return 1; 
     84            } 
     85 
     86            return 0; 
    6187} 
    6288 
     
    7096{ 
    7197    Match matches[MAX_MATCHES]; 
    72     uint32_t *buf; 
     98    uint32_t *buf, *p; 
    7399    FILE *f; 
    74100    int size; 
     
    76102    int fail, success; 
    77103    uint32_t base; 
    78     FuncSig *sig; 
     104    FuncSig *sig, *s; 
    79105    int count; 
    80106    int ret = 0; 
    81107    const char *curr_name; 
     108    BufRange *n; 
     109 
     110    clock_t t1 = clock(); 
    82111 
    83112    if (argc != 3) 
    84         usage(); 
     113        usage(); 
    85114 
    86115    f = fopen(argv[1], "r+b"); 
    87116 
    88117    if (f == NULL) 
    89         usage(); 
     118        usage(); 
    90119 
    91120    base = strtoul(argv[2], NULL, 0); 
     
    98127    fseek(f,0,SEEK_SET); 
    99128 
    100     buf=malloc(size*4); 
     129    // Max sig size if 32, add extra space at end of buffer and fill with 0xFFFFFFFF 
     130    // Allows sig matching past end of firmware without checking each time in the inner loop 
     131    buf=malloc((size+32)*4); 
    101132    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     } 
     133    fclose(f); 
     134    memset(&buf[size],0xff,32*4); 
     135 
     136    // Find all the valid ranges for checking (skips over large blocks of 0xFFFFFFFF) 
     137    br = 0; last = 0; 
     138    k = -1; j = 0; 
     139    for (i = 0; i < size; i++) 
     140    { 
     141        if (buf[i] == 0xFFFFFFFF)   // Possible start of block to skip 
     142        { 
     143            if (k == -1)            // Mark start of possible skip block 
     144            { 
     145                k = i; 
     146            } 
     147        } 
     148        else                        // Found end of block ? 
     149        { 
     150            if (k != -1) 
     151            { 
     152                if (i - k > 32)     // If block more than 32 words then we want to skip it 
     153                { 
     154                    if (k - j > 8) 
     155                    { 
     156                        // Add a range record for the previous valid range (ignore short ranges) 
     157                        addBufRange(&buf[j],k - j); 
     158                    } 
     159                    j = i;          // Reset valid range start to current position 
     160                } 
     161                k = -1;             // Reset marker for skip block 
     162            } 
     163        } 
     164    } 
     165    // Add range for last valid block 
     166    if (k != -1)     
     167    { 
     168        if (i - k > 32) 
     169        { 
     170            if (k - j > 8) 
     171            { 
     172                addBufRange(&buf[j],k - j); 
     173            } 
     174        } 
     175    } 
     176    else 
     177    { 
     178        if (i - j > 8) 
     179        { 
     180            addBufRange(&buf[j], i - j); 
     181        } 
     182    } 
     183 
     184    for (k = 0; func_list[k].name; k++){ 
     185 
     186        count = 0; 
     187        curr_name = func_list[k].name; 
     188 
     189        while (1) { 
     190            sig = func_list[k].sig; 
     191 
     192            for (n = br; n != 0; n = n->next){ 
     193                for (p = n->p, i = 0; i < n->len; p++, i++){ 
     194                    fail = 0; 
     195                    success = 0; 
     196                    for (s = sig; s->offs != -1; s++){ 
     197                        if ((p[s->offs] & s->mask) != s->value){ 
     198                            fail++; 
     199                        } else { 
     200                            success++; 
     201                        } 
     202                    } 
     203                    if (success > fail){ 
     204                        matches[count].ptr = base+(i<<2); 
     205                        matches[count].success = success; 
     206                        matches[count].fail = fail; 
     207                        count ++; 
     208                        if (count >= MAX_MATCHES){ 
     209                            printf("// WARNING: too many matches for %s!\n", func_list[k].name); 
     210                            break; 
     211                        } 
     212                    } 
     213                } 
     214            } 
     215 
     216            // same name, so we have another version of the same function 
     217            if ((func_list[k+1].name == NULL) || (strcmp(curr_name, func_list[k+1].name) != 0)) { 
     218                break; 
     219            } 
     220            k++; 
     221        } 
     222 
     223        // find best match and report results 
     224        if (count == 0){ 
     225            printf("// ERROR: %s is not found!\n", curr_name); 
     226            ret = 1; 
     227        } else { 
     228            if (count > 1){ 
     229                qsort(matches, count, sizeof(Match), (void*)match_compare); 
     230            } 
     231 
     232            if (matches->fail > 0) 
     233                printf("// Best match: %d%%\n", matches->success*100/(matches->success+matches->fail)); 
     234 
     235            printf("NSTUB(%s, 0x%x)\n", curr_name, matches->ptr); 
     236 
     237            for (i=1;i<count && matches[i].fail==matches[0].fail;i++){ 
     238                printf("// ALT: NSTUB(%s, 0x%x) // %d/%d\n", curr_name, matches[i].ptr, matches[i].success, matches[i].fail); 
     239            } 
     240        } 
     241    } 
     242 
     243    clock_t t2 = clock(); 
     244 
     245    fprintf(stderr,"Time to generate stubs %.2f seconds\n",(double)(t2-t1)/(double)CLOCKS_PER_SEC); 
    159246 
    160247    return ret; 
Note: See TracChangeset for help on using the changeset viewer.