# HG changeset patch # User Matti Hamalainen # Date 1543490162 -7200 # Node ID 45ad06bb60c4c4b6d3a4589f3e5d273a6f1d7337 # Parent cf966e66c9af9ba787ffde5ee1612ce6b221d1e6 Implement offset dump mode in fanalyze. diff -r cf966e66c9af -r 45ad06bb60c4 tools/fanalyze.c --- 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 [,[8|16|32]]", OPT_ARGREQ }, + { 2, 'g', "grep", "Binary grep [,[8|16|32]]", OPT_ARGREQ }, + { 3, 'o', "offset", "Show data in offset ,[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: