changeset 2034:45ad06bb60c4

Implement offset dump mode in fanalyze.
author Matti Hamalainen <ccr@tnsp.org>
date Thu, 29 Nov 2018 13:16:02 +0200
parents cf966e66c9af
children 472ca1dbc2d3
files tools/fanalyze.c
diffstat 1 files changed, 259 insertions(+), 154 deletions(-) [+]
line wrap: on
line diff
--- a/tools/fanalyze.c	Tue Nov 27 13:40:31 2018 +0200
+++ b/tools/fanalyze.c	Thu Nov 29 13:16:02 2018 +0200
@@ -12,7 +12,7 @@
 
 #define SET_MAX_FILES    64
 #define SET_MAX_ELEMS    256
-#define SET_MAX_VALUES   32
+#define SET_MAX_VALUES   64
 
 
 /* Typedefs
@@ -62,8 +62,15 @@
 
 typedef struct
 {
+    int type;
+    Uint32 value;
+} DMGrepValue;
+
+
+typedef struct
+{
     char *name;
-    uint32_t nmax;
+    Uint32 nmax;
     unsigned int bsize;
 } DMGrepDef;
 
@@ -78,15 +85,17 @@
 };
 
 
-typedef struct
+enum
 {
-    int type;
-    uint32_t value;
-} DMGrepValue;
+    FA_ANALYZE,
+    FA_GREP,
+    FA_OFFSET,
+};
 
 
 /* Global variables
  */
+int            setMode = FA_ANALYZE;
 int            nsrcFiles = 0;              // Number of source files
 DMSourceFile   srcFiles[SET_MAX_FILES];    // Source file names
 DMStats        totalStats;
@@ -100,7 +109,8 @@
 {
     {  0, '?', "help",        "Show this help", OPT_NONE },
     {  1, 'v', "verbose",     "Be more verbose", OPT_NONE },
-    {  2, 'g', "grep",        "Binary grep mode <val>[,<le|be>[8|16|32]]", OPT_ARGREQ },
+    {  2, 'g', "grep",        "Binary grep <val>[,<le|be>[8|16|32]]", OPT_ARGREQ },
+    {  3, 'o', "offset",      "Show data in offset <offset>,<le|be>[8|16|32]]", OPT_ARGREQ },
 };
 
 static const int optListN = sizeof(optList) / sizeof(optList[0]);
@@ -113,12 +123,19 @@
 }
 
 
-int argParseGrepValue(const char *arg)
+int argParseGrepValue(const char *arg, const int mode)
 {
     const char *sep = strchr(arg, ',');
     char *vspec, *vstr;
     int vtype = -1, ret = DMERR_OK;
-    uint32_t vval;
+    Uint32 vval;
+
+    if (setMode != FA_ANALYZE && setMode != mode)
+    {
+        dmErrorMsg("Options specifying multiple operating modes can't be used.\n");
+        return DMERR_INVALID_ARGS;
+    }
+    setMode = mode;
 
     // Do we have spec?
     if (sep != NULL)
@@ -178,33 +195,42 @@
         goto out;
     }
 
-    // Check if we need to guess size
-    if (vtype < 0)
+    if (mode == FA_GREP)
     {
-        for (int n = DMGV_last; n >= 0; n--)
+        // Check if we need to guess size
+        if (vtype < 0)
+        {
+            for (int n = DMGV_last; n >= 0; n--)
+            {
+                const DMGrepDef *def = &dmGrepTypes[n];
+                if (vval <= def->nmax)
+                    vtype = n;
+            }
+        }
+
+        if (vtype < 0)
         {
-            const DMGrepDef *def = &dmGrepTypes[n];
-            if (vval <= def->nmax)
-                vtype = n;
+            ret = dmError(DMERR_INVALID_ARGS,
+                "Could not guess value type for '%s'.\n",
+                arg);
+            goto out;
+        }
+
+        // Check range
+        if (vval > dmGrepTypes[vtype].nmax)
+        {
+            ret = dmError(DMERR_INVALID_ARGS,
+                "Integer value %d <= %d <= %d out of range for type %s.\n",
+                vval, 0, dmGrepTypes[vtype].nmax, dmGrepTypes[vtype].name);
+
+            goto out;
         }
     }
-
-    if (vtype < 0)
+    else
+    if (mode == FA_OFFSET)
     {
-        ret = dmError(DMERR_INVALID_ARGS,
-            "Could not guess value type for '%s'.\n",
-            arg);
-        goto out;
-    }
-
-    // Check range
-    if (vval > dmGrepTypes[vtype].nmax)
-    {
-        ret = dmError(DMERR_INVALID_ARGS,
-            "Integer value %d <= %d <= %d out of range for type %s.\n",
-            vval, 0, dmGrepTypes[vtype].nmax, dmGrepTypes[vtype].name);
-
-        goto out;
+        if (vtype < 0)
+            vtype = DMGV_uint8;
     }
 
     if (nsetGrepValues < SET_MAX_VALUES)
@@ -220,7 +246,7 @@
     else
     {
         ret = dmError(DMERR_BOUNDS,
-            "Too many greps specified (max %d).",
+            "Too many values specified (max %d).",
             SET_MAX_VALUES);
     }
 
@@ -247,7 +273,10 @@
             break;
 
         case 2:
-            return argParseGrepValue(optArg) == DMERR_OK;
+            return argParseGrepValue(optArg, FA_GREP) == DMERR_OK;
+
+        case 3:
+            return argParseGrepValue(optArg, FA_OFFSET) == DMERR_OK;
 
         default:
             dmErrorMsg("Unknown argument '%s'.\n", currArg);
@@ -307,6 +336,41 @@
 }
 
 
+BOOL dmGetData(const int type, const DMSourceFile *file, const size_t offs, Uint32 *mval)
+{
+    Uint8 *data = file->data + offs;
+    if (offs + dmGrepTypes[type].bsize >= file->size)
+        return FALSE;
+    
+    switch (type)
+    {
+        case DMGV_uint8:
+            *mval = *((uint8_t *) data);
+            break;
+
+        case DMGV_uint16_le:
+            *mval = DM_LE16_TO_NATIVE(*((Uint16 *) data));
+            break;
+
+        case DMGV_uint16_be:
+            *mval = DM_BE16_TO_NATIVE(*((Uint16 *) data));
+            break;
+
+        case DMGV_uint32_le:
+            *mval = DM_LE32_TO_NATIVE(*((Uint32 *) data));
+            break;
+
+        case DMGV_uint32_be:
+            *mval = DM_BE32_TO_NATIVE(*((Uint32 *) data));
+            break;
+
+        default:
+            return FALSE;
+    }
+    return TRUE;
+}
+
+
 int main(int argc, char *argv[])
 {
     DMCompElem *compBuf = NULL;
@@ -351,13 +415,15 @@
     }
 
 
-    // Check if we are in grep mode
-    if (nsetGrepValues > 0)
+    //
+    // Check what operating mode we are in
+    //
+    if (setMode == FA_GREP)
     {
         for (int nfile = 0; nfile < nsrcFiles; nfile++)
         {
             DMSourceFile *file = &srcFiles[nfile];
-            dmPrint(0, "\n%s:\n", file->filename);
+            dmPrint(0, "\n%s\n", file->filename);
 
             for (int n = 0; n < nsetGrepValues; n++)
             {
@@ -366,162 +432,201 @@
 
                 for (size_t offs = 0; offs + def->bsize < file->size; offs++)
                 {
-                    uint32_t mval = -1;
-                    switch (node->type)
-                    {
-                        case DMGV_uint8:
-                            mval = *((uint8_t *) (file->data + offs));
-                            break;
-
-                        case DMGV_uint16_le:
-                            mval = DM_LE16_TO_NATIVE(*((uint16_t *) (file->data + offs)));
-                            break;
-
-                        case DMGV_uint16_be:
-                            mval = DM_BE16_TO_NATIVE(*((uint16_t *) (file->data + offs)));
-                            break;
-
-                        case DMGV_uint32_le:
-                            mval = DM_LE32_TO_NATIVE(*((uint32_t *) (file->data + offs)));
-                            break;
-
-                        case DMGV_uint32_be:
-                            mval = DM_BE32_TO_NATIVE(*((uint32_t *) (file->data + offs)));
-                            break;
-                    }
+                    Uint32 mval;
+                    dmGetData(node->type, file, offs, &mval);
 
                     if (mval == node->value)
                     {
                         dmPrint(0, "%08x : %s match %d / 0x%x\n",
                             offs, def->name, mval, mval);
-
                     }
                 }
             }
         }
-        goto out;
-    }
-
-    // Allocate comparision buffer
-    // XXX: integer overflow?
-    dmPrint(2, "Allocating %d element (%d bytes) comparision buffer.\n",
-        compBufSize, compBufSize * sizeof(DMCompElem));
-
-    if ((compBuf = dmCalloc(compBufSize, sizeof(DMCompElem))) == NULL)
-    {
-        dmErrorMsg("Out of memory. Could not allocate comparision buffer!\n");
-        goto out;
     }
-
-    // Begin analyzing ..
-    dmPrint(2, "Analyzing ..\n");
-    for (int nfile = 0; nfile < nsrcFiles; nfile++)
+    else
+    if (setMode == FA_OFFSET)
     {
-        DMSourceFile *file = &srcFiles[nfile];
+        for (int nfile = 0; nfile < nsrcFiles; nfile++)
+        {
+            DMSourceFile *file = &srcFiles[nfile];
+            dmPrint(1, "#%03d: %s\n", nfile + 1, file->filename);
+        }
 
-        for (size_t offs = 0; offs < file->size; offs++)
+        printf("  offset :");
+        for (int nfile = 0; nfile < nsrcFiles; nfile++)
+            printf("    %03d   ", nfile + 1);
+        printf("\n");
+
+        printf("==========");
+        for (int nfile = 0; nfile < nsrcFiles; nfile++)
+            printf("===========");
+        printf("\n");
+
+        for (int n = 0; n < nsetGrepValues; n++)
         {
-            Uint8 bv = file->data[offs];
-            totalStats.cv[bv].count++;
-            file->stats.cv[bv].count++;
+            DMGrepValue *node = &setGrepValues[n];
+            const DMGrepDef *def = &dmGrepTypes[node->type];
+            printf("%08x : ", node->value);
+
+            for (int nfile = 0; nfile < nsrcFiles; nfile++)
+            {
+                DMSourceFile *file = &srcFiles[nfile];
+                Uint32 mval;
+                char mfmt[32];
+                int npad, nwidth;
+
+                if (dmGetData(node->type, file, node->value, &mval))
+                {
+                    snprintf(mfmt, sizeof(mfmt), "%%0%dx", def->bsize * 2);
+                    nwidth = def->bsize * 2;
+                }
+                else
+                {
+                    strcpy(mfmt, "----");
+                    nwidth = 4;
+                }
+
+                npad = (10 - nwidth) / 2;
+                for (int q = 0; q < npad; q++)
+                    putchar(' ');
+                    
+                printf(mfmt, mval);
+
+                for (int q = 0; q < npad; q++)
+                    putchar(' ');
+            }
+            printf("\n");
+        }
+    }
+    else
+    if (setMode == FA_ANALYZE)
+    {
+        // Allocate comparision buffer
+        // XXX: integer overflow?
+        dmPrint(2, "Allocating %d element (%d bytes) comparision buffer.\n",
+            compBufSize, compBufSize * sizeof(DMCompElem));
+
+        if ((compBuf = dmCalloc(compBufSize, sizeof(DMCompElem))) == NULL)
+        {
+            dmErrorMsg("Out of memory. Could not allocate comparision buffer!\n");
+            goto out;
+        }
+
+        // Begin analyzing ..
+        dmPrint(2, "Analyzing ..\n");
+        for (int nfile = 0; nfile < nsrcFiles; nfile++)
+        {
+            DMSourceFile *file = &srcFiles[nfile];
+
+            for (size_t offs = 0; offs < file->size; offs++)
+            {
+                Uint8 bv = file->data[offs];
+                totalStats.cv[bv].count++;
+                file->stats.cv[bv].count++;
+            }
+
+            for (size_t offs = 0; offs < compBufSize; offs++)
+            {
+                Uint8 data = offs < file->size ? file->data[offs] : 0;
+                compBuf[offs].stats[data]++;
+            }
         }
 
         for (size_t offs = 0; offs < compBufSize; offs++)
         {
-            Uint8 data = offs < file->size ? file->data[offs] : 0;
-            compBuf[offs].stats[data]++;
+            DMCompElem *el = &compBuf[offs];
+            for (int n = 0; n < SET_MAX_ELEMS; n++)
+            {
+                if (el->stats[n] > 0)
+                {
+                    el->variants++;
+                    el->data = n;
+                }
+            }
         }
-    }
 
-    for (size_t offs = 0; offs < compBufSize; offs++)
-    {
-        DMCompElem *el = &compBuf[offs];
-        for (int n = 0; n < SET_MAX_ELEMS; n++)
+        // Display results
+        for (size_t offs = 0, n = 0; offs < compBufSize; offs++)
         {
-            if (el->stats[n] > 0)
+            DMCompElem *el = &compBuf[offs];
+            BOOL var = el->variants > 1;
+
+            if (n == 0)
+                printf("%08" DM_PRIx_SIZE_T " | ", offs);
+
+            if (var)
+                printf("[%2d] ", el->variants);
+            else
+                printf(" %02x  ", el->data);
+
+            if (++n >= 16)
             {
-                el->variants++;
-                el->data = n;
+                printf("\n");
+                n = 0;
             }
         }
-    }
 
-    // Display results
-    for (size_t offs = 0, n = 0; offs < compBufSize; offs++)
-    {
-        DMCompElem *el = &compBuf[offs];
-        BOOL var = el->variants > 1;
+        printf("\n");
 
-        if (n == 0)
-            printf("%08" DM_PRIx_SIZE_T " | ", offs);
+        // Attempt further analysis
+        for (int nfile = 0; nfile < nsrcFiles; nfile++)
+        {
+            DMSourceFile *file = &srcFiles[nfile];
+            size_t len = file->size > compBufSize ? compBufSize : file->size;
+            for (size_t offs = 0; offs + 4 < len; offs++)
+            {
+                DMCompElem *elem = &compBuf[offs];
 
-        if (var)
-            printf("[%2d] ", el->variants);
-        else
-            printf(" %02x  ", el->data);
+                for (int variant = 3; variant >= 0; variant--)
+                {
+                    size_t nmax = (variant < 2) ? sizeof(Uint16) : sizeof(Uint32);
+                    Uint32 tmp = 0;
 
-        if (++n >= 16)
-        {
-            printf("\n");
-            n = 0;
-        }
-    }
+                    for (size_t n = 0; n < nmax; n++)
+                    {
+                        size_t boffs = (variant & 1) ? n : nmax - n;
+
+                        tmp <<= 8;
+                        tmp |= file->data[offs + boffs];
+                    }
 
-    printf("\n");
+                    if (file->size - tmp < 32)
+                    {
+                        elem->interest[variant] += 32 - (file->size - tmp);
+                        elem->interestF[variant]++;
+                    }
+                }
+            }
+        }
 
-    // Attempt further analysis
-    for (int nfile = 0; nfile < nsrcFiles; nfile++)
-    {
-        DMSourceFile *file = &srcFiles[nfile];
-        size_t len = file->size > compBufSize ? compBufSize : file->size;
-        for (size_t offs = 0; offs + 4 < len; offs++)
+        printf("\nMore findings:\n");
+        for (size_t offs = 0; offs + 4 < compBufSize; offs++)
         {
             DMCompElem *elem = &compBuf[offs];
 
-            for (int variant = 3; variant >= 0; variant--)
+            for (int variant = 0; variant < 4; variant++)
+            if (elem->interestF[variant] > 0)
             {
-                size_t nmax = (variant < 2) ? sizeof(Uint16) : sizeof(Uint32);
-                Uint32 tmp = 0;
-
-                for (size_t n = 0; n < nmax; n++)
-                {
-                    size_t boffs = (variant & 1) ? n : nmax - n;
+                printf("%08" DM_PRIx_SIZE_T " | V%d : %d / %d\n",
+                offs, variant,
+                elem->interestF[variant], elem->interest[variant]);
+            }
+        }
 
-                    tmp <<= 8;
-                    tmp |= file->data[offs + boffs];
-                }
+        printf("\nGlobal most used bytes:\n");
+        dmPrintStats(&totalStats, 16, totalSize);
 
-                if (file->size - tmp < 32)
-                {
-                    elem->interest[variant] += 32 - (file->size - tmp);
-                    elem->interestF[variant]++;
-                }
-            }
+        for (int nfile = 0; nfile < nsrcFiles; nfile++)
+        {
+            DMSourceFile *file = &srcFiles[nfile];
+            printf("Most used bytes for '%s':\n", file->filename);
+            dmPrintStats(&file->stats, 16, file->size);
         }
     }
-
-    printf("\nMore findings:\n");
-    for (size_t offs = 0; offs + 4 < compBufSize; offs++)
+    else
     {
-        DMCompElem *elem = &compBuf[offs];
-
-        for (int variant = 0; variant < 4; variant++)
-        if (elem->interestF[variant] > 0)
-        {
-            printf("%08" DM_PRIx_SIZE_T " | V%d : %d / %d\n",
-            offs, variant,
-            elem->interestF[variant], elem->interest[variant]);
-        }
-    }
-
-    printf("\nGlobal most used bytes:\n");
-    dmPrintStats(&totalStats, 16, totalSize);
-
-    for (int nfile = 0; nfile < nsrcFiles; nfile++)
-    {
-        DMSourceFile *file = &srcFiles[nfile];
-        printf("Most used bytes for '%s':\n", file->filename);
-        dmPrintStats(&file->stats, 16, file->size);
+        dmErrorMsg("Invalid operating mode?\n");
     }
 
 out: