diff --git a/librz/arch/pdb_process.c b/librz/arch/pdb_process.c index 981e63c0e1..bc8d63e154 100644 --- a/librz/arch/pdb_process.c +++ b/librz/arch/pdb_process.c @@ -17,7 +17,7 @@ static RzType *array_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdb static void arglist_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *arglist, RzPVector /**/ *vec); static RzType *mfunction_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info, char *name); static RzType *onemethod_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info); -static RzType *member_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info, char *name); +static RzType *member_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info, char *name, ut64 *bitfield_width); static RzType *nest_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *t, char *name); static RzType *union_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type); static RzTypeUnionMember *union_member_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info); @@ -240,7 +240,7 @@ static RzType *onemethod_parse( return NULL; } -static RzType *member_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info, char *name) { +static RzType *member_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info, char *name, ut64 *bitfield_width) { rz_return_val_if_fail(type_info && typedb, NULL); Tpi_LF_Member *lf_member = type_info->data; @@ -248,6 +248,23 @@ static RzType *member_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPd if (!utype) { return NULL; } + if (utype->kind == TpiKind_BITFIELD) { + // A bitfield member ("int a : 4;"): resolve the member to its underlying + // integer type and report the bit width via \p bitfield_width, so it is + // stored as a bitfield (see RzTypeStructMember.size / RzTypeUnionMember.size). + Tpi_LF_Bitfield *lf_bitfield = utype->data; + if (!lf_bitfield) { + return NULL; + } + if (bitfield_width) { + *bitfield_width = lf_bitfield->length; + } + RzPdbTpiType *base = rz_bin_pdb_get_type_by_index(stream, lf_bitfield->base_type); + if (!base) { + return NULL; + } + return pdb_type_parse(typedb, stream, base, name); + } return pdb_type_parse(typedb, stream, utype, name); } @@ -321,6 +338,7 @@ static RzTypeStructMember *class_member_parse( rz_return_val_if_fail(t, NULL); char *name = NULL; ut64 offset = 0; + ut64 bitfield_width = 0; RzType *type = NULL; switch (t->kind) { case TpiKind_ONEMETHOD: { @@ -331,7 +349,7 @@ static RzTypeStructMember *class_member_parse( case TpiKind_MEMBER: { offset = rz_bin_pdb_get_type_val(t); name = rz_bin_pdb_get_type_name(t); - type = member_parse(typedb, stream, t, name); + type = member_parse(typedb, stream, t, name, &bitfield_width); break; } case TpiKind_STMEMBER: { @@ -371,6 +389,7 @@ static RzTypeStructMember *class_member_parse( member->name = rz_str_dup(name); member->type = type; member->offset = offset; + member->size = bitfield_width; // bitfield width in bits, 0 if not a bitfield return member; cleanup: rz_type_free(type); @@ -512,6 +531,7 @@ static RzTypeUnionMember *union_member_parse(const RzTypeDB *typedb, RzPdbTpiStr rz_return_val_if_fail(type_info && stream && typedb, NULL); char *name = NULL; ut64 offset = 0; + ut64 bitfield_width = 0; RzType *type = NULL; switch (type_info->kind) { case TpiKind_ONEMETHOD: { @@ -522,7 +542,7 @@ static RzTypeUnionMember *union_member_parse(const RzTypeDB *typedb, RzPdbTpiStr case TpiKind_MEMBER: { offset = rz_bin_pdb_get_type_val(type_info); name = rz_bin_pdb_get_type_name(type_info); - type = member_parse(typedb, stream, type_info, name); + type = member_parse(typedb, stream, type_info, name, &bitfield_width); break; } case TpiKind_NESTTYPE: { @@ -547,6 +567,7 @@ static RzTypeUnionMember *union_member_parse(const RzTypeDB *typedb, RzPdbTpiStr member->name = rz_str_dup(name); member->type = type; member->offset = offset; + member->size = bitfield_width; // bitfield width in bits, 0 if not a bitfield return member; cleanup: rz_type_free(type); diff --git a/test/db/cmd/cmd_idp b/test/db/cmd/cmd_idp index 603e63ee3a..8eb6c29fd8 100644 --- a/test/db/cmd/cmd_idp +++ b/test/db/cmd/cmd_idp @@ -110,7 +110,21 @@ EXPECT=<