diff --git a/cffdump/cffdec.c b/cffdump/cffdec.c index a83a3e45..1bc767b2 100644 --- a/cffdump/cffdec.c +++ b/cffdump/cffdec.c @@ -919,8 +919,27 @@ dump_domain(uint32_t *dwords, uint32_t sizedwords, int level, char *decoded; if (!(info && info->typeinfo)) break; - decoded = rnndec_decodeval(rnn->vc, info->typeinfo, dwords[i]); - printf("%s%s\n", levels[level], decoded); + uint64_t value = dwords[i]; + if (info->typeinfo->high >= 32 && i < sizedwords - 1) { + value |= (uint64_t) dwords[i + 1] << 32; + i++; /* skip the next dword since we're printing it now */ + } + decoded = rnndec_decodeval(rnn->vc, info->typeinfo, value); + /* Unlike the register printing path, we don't print the name + * of the register, so if it doesn't contain other named + * things (i.e. it isn't a bitset) then print the register + * name as if it's a bitset with a single entry. This avoids + * having to create a dummy register with a single entry to + * get a name in the decoding. + */ + if (info->typeinfo->type == RNN_TTYPE_BITSET || + info->typeinfo->type == RNN_TTYPE_INLINE_BITSET) { + printf("%s%s\n", levels[level], decoded); + } else { + printf("%s{ %s%s%s = %s }\n", levels[level], + rnn->vc->colors->rname, info->name, + rnn->vc->colors->reset, decoded); + } free(decoded); free(info->name); free(info); diff --git a/include/rnn.h b/include/rnn.h index 935ae840..521d1f80 100644 --- a/include/rnn.h +++ b/include/rnn.h @@ -138,6 +138,7 @@ struct rnntypeinfo { int valsmax; int shr, low, high; uint64_t min, max, align, radix; + int addvariant; int minvalid, maxvalid, alignvalid, radixvalid; }; diff --git a/rnn/rnn.c b/rnn/rnn.c index 96d05215..c89c6ed2 100644 --- a/rnn/rnn.c +++ b/rnn/rnn.c @@ -198,6 +198,8 @@ static int trytypeattr (struct rnndb *db, char *file, xmlNode *node, xmlAttr *at } else if (!strcmp(attr->name, "high")) { ti->high = getnumattrib(db, file, node->line, attr); return 1; + } else if (!strcmp(attr->name, "addvariant")) { + ti->addvariant = getboolattrib(db, file, node->line, attr); } return 0; } @@ -943,6 +945,7 @@ static void copytypeinfo (struct rnntypeinfo *dst, struct rnntypeinfo *src, char dst->min = src->min; dst->max = src->max; dst->align = src->align; + dst->addvariant = src->addvariant; for (i = 0; i < src->valsnum; i++) ADDARRAY(dst->vals, copyvalue(src->vals[i], file)); for (i = 0; i < src->bitfieldsnum; i++) @@ -1187,6 +1190,10 @@ static void preptypeinfo(struct rnndb *db, struct rnntypeinfo *ti, char *prefix, ti->name = "hex"; ti->type = RNN_TTYPE_HEX; } + if (ti->addvariant && ti->type != RNN_TTYPE_ENUM) { + fprintf (stderr, "%s: addvariant specified on non-enum type %s\n", prefix, ti->name); + db->estatus = 1; + } for (i = 0; i < ti->bitfieldsnum; i++) prepbitfield(db, ti->bitfields[i], prefix, vi); for (i = 0; i < ti->valsnum; i++) diff --git a/rnn/rnndec.c b/rnn/rnndec.c index 39d38b41..fcf25971 100644 --- a/rnn/rnndec.c +++ b/rnn/rnndec.c @@ -45,7 +45,7 @@ int rnndec_varadd(struct rnndeccontext *ctx, char *varset, char *variant) { fprintf (stderr, "Enum %s doesn't exist in database!\n", varset); return 0; } - int i; + int i, j; for (i = 0; i < en->valsnum; i++) if (!strcasecmp(en->vals[i]->name, variant)) { struct rnndecvariant *ci = calloc (sizeof *ci, 1); @@ -54,8 +54,27 @@ int rnndec_varadd(struct rnndeccontext *ctx, char *varset, char *variant) { ADDARRAY(ctx->vars, ci); return 1; } - fprintf (stderr, "Variant %s doesn't exist in enum %s!\n", variant, varset); - return 0; + + if (i == en->valsnum) { + fprintf (stderr, "Variant %s doesn't exist in enum %s!\n", variant, varset); + return 0; + } + + for (j = 0; j < ctx->varsnum; j++) { + if (ctx->vars[j]->en == en) { + ctx->vars[j]->variant = i; + break; + } + } + + if (i == ctx->varsnum) { + struct rnndecvariant *ci = calloc (sizeof *ci, 1); + ci->en = en; + ci->variant = i; + ADDARRAY(ctx->vars, ci); + } + + return 1; } int rnndec_varmatch(struct rnndeccontext *ctx, struct rnnvarinfo *vi) { @@ -159,6 +178,9 @@ char *rnndec_decodeval(struct rnndeccontext *ctx, struct rnntypeinfo *ti, uint64 tmp = rnndec_decode_enum_val(ctx, vals, valsnum, value); if (tmp) { asprintf (&res, "%s%s%s", ctx->colors->eval, tmp, ctx->colors->reset); + if (ti->addvariant) { + rnndec_varadd(ctx, ti->eenum->name, tmp); + } break; } goto failhex;