librz/arch/pdb: wire LF_BITFIELD members to the bitfield width (#6452)
Follow-up to the C bitfield support added in #6439 (#1240, #314): the PDB type parser dropped struct/union bitfield members because an LF_BITFIELD member type resolved to NULL in pdb_type_parse(), so "tc"/"ts"/"tp" on a PDB-loaded type lost every bitfield field. member_parse() now detects a TpiKind_BITFIELD field type, resolves the member to the bitfield's underlying integer (base_type) and reports the bit width (length) via an out-parameter. class_member_parse() and union_member_parse() store it in RzTypeStructMember.size / RzTypeUnionMember.size (the bitfield width in bits, 0 if not a bitfield), matching the convention used by the C and DWARF member paths. Update the PDB type expectations that previously asserted bitfield_typedef had no members: db/cmd/cmd_idp (idpij) and db/tools/rz_bin (rz-bin -Pj) now expect the three resolved "unsigned char" members of minimal.pdb. Co-authored-by: Anton Kochkov <anton.kochkov@gmail.com>
This commit is contained in:
parent
d723950a62
commit
92972bcfb2
3 changed files with 41 additions and 6 deletions
|
|
@ -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 /*<RzCallableArg *>*/ *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);
|
||||
|
|
|
|||
|
|
@ -110,7 +110,21 @@ EXPECT=<<EOF
|
|||
"name": "bitfield_typedef",
|
||||
"size": 1,
|
||||
"members": [
|
||||
|
||||
{
|
||||
"member_type": "unsigned char",
|
||||
"member_name": "a",
|
||||
"offset": 0
|
||||
},
|
||||
{
|
||||
"member_type": "unsigned char",
|
||||
"member_name": "b",
|
||||
"offset": 0
|
||||
},
|
||||
{
|
||||
"member_type": "unsigned char",
|
||||
"member_name": "c",
|
||||
"offset": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1306,7 +1306,7 @@ FILE=bins/pdb/minimal.pdb
|
|||
TOOL=rz-bin
|
||||
ARGS=-Pj
|
||||
EXPECT=<<EOF
|
||||
{"pdb":[{"modules":[{"module_name":"* Linker Generated Manifest RES *","object_file_name":""},{"module_name":"C:\\Users\\emuresan\\source\\repos\\minimal\\Release\\main.obj","object_file_name":"C:\\Users\\emuresan\\source\\repos\\minimal\\Release\\main.obj"},{"module_name":"* Linker *","object_file_name":""}]},{"types":[{"type":"structure","name":"struct_typedef","size":7,"members":[{"member_type":"char","member_name":"a","offset":0},{"member_type":"int16_t","member_name":"b","offset":1},{"member_type":"int32_t","member_name":"c","offset":3}]},{"type":"union","name":"type_0x1004","size":4,"members":[{"member_type":"char [4]","member_name":"a","offset":0},{"member_type":"int32_t","member_name":"b","offset":0}]},{"type":"structure","name":"unnamed_member_types_typedef","size":8,"members":[{"member_type":"union type_0x1004","member_name":"a","offset":0},{"member_type":"int32_t","member_name":"b","offset":4}]},{"type":"structure","name":"bitfield_typedef","size":1,"members":[]},{"type":"union","name":"union_typedef","size":4,"members":[{"member_type":"char","member_name":"a","offset":0},{"member_type":"int16_t","member_name":"b","offset":0},{"member_type":"int32_t","member_name":"c","offset":0}]}]},{"gvars":[{"address":12292,"symtype":4366,"section_name":".data","gdata_name":"_uninitialized_global"},{"address":12288,"symtype":4366,"section_name":".data","gdata_name":"_initialized_global"},{"address":4096,"symtype":4366,"section_name":".text","gdata_name":"_function"},{"address":4182,"symtype":4366,"section_name":".text","gdata_name":"_mainCRTStartup"},{"address":4120,"symtype":4366,"section_name":".text","gdata_name":"_main"}]}]}
|
||||
{"pdb":[{"modules":[{"module_name":"* Linker Generated Manifest RES *","object_file_name":""},{"module_name":"C:\\Users\\emuresan\\source\\repos\\minimal\\Release\\main.obj","object_file_name":"C:\\Users\\emuresan\\source\\repos\\minimal\\Release\\main.obj"},{"module_name":"* Linker *","object_file_name":""}]},{"types":[{"type":"structure","name":"struct_typedef","size":7,"members":[{"member_type":"char","member_name":"a","offset":0},{"member_type":"int16_t","member_name":"b","offset":1},{"member_type":"int32_t","member_name":"c","offset":3}]},{"type":"union","name":"type_0x1004","size":4,"members":[{"member_type":"char [4]","member_name":"a","offset":0},{"member_type":"int32_t","member_name":"b","offset":0}]},{"type":"structure","name":"unnamed_member_types_typedef","size":8,"members":[{"member_type":"union type_0x1004","member_name":"a","offset":0},{"member_type":"int32_t","member_name":"b","offset":4}]},{"type":"structure","name":"bitfield_typedef","size":1,"members":[{"member_type":"unsigned char","member_name":"a","offset":0},{"member_type":"unsigned char","member_name":"b","offset":0},{"member_type":"unsigned char","member_name":"c","offset":0}]},{"type":"union","name":"union_typedef","size":4,"members":[{"member_type":"char","member_name":"a","offset":0},{"member_type":"int16_t","member_name":"b","offset":0},{"member_type":"int32_t","member_name":"c","offset":0}]}]},{"gvars":[{"address":12292,"symtype":4366,"section_name":".data","gdata_name":"_uninitialized_global"},{"address":12288,"symtype":4366,"section_name":".data","gdata_name":"_initialized_global"},{"address":4096,"symtype":4366,"section_name":".text","gdata_name":"_function"},{"address":4182,"symtype":4366,"section_name":".text","gdata_name":"_mainCRTStartup"},{"address":4120,"symtype":4366,"section_name":".text","gdata_name":"_main"}]}]}
|
||||
EOF
|
||||
RUN
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue