From bfe19a784b5d9874c93d87aa50437ad1157cbf32 Mon Sep 17 00:00:00 2001 From: billow Date: Wed, 6 Dec 2023 13:57:41 +0800 Subject: [PATCH] Create global variables from PDB (#4021) --- librz/analysis/meson.build | 2 +- librz/analysis/{type_pdb.c => pdb_process.c} | 176 ++-- librz/bin/meson.build | 1 + librz/bin/pdb/gdata.c | 79 +- librz/bin/pdb/gdata.h | 18 - librz/bin/pdb/omap.c | 73 +- librz/bin/pdb/pdb.c | 42 +- librz/bin/pdb/pdb.h | 10 +- librz/bin/pdb/stream_pe.h | 4 + librz/bin/pdb/symbol.c | 182 ++++ librz/bin/pdb/symbol.h | 100 +++ librz/bin/pdb/symbol_enum.h | 283 ++++++ librz/bin/pdb/tpi.c | 889 +++++++++---------- librz/bin/pdb/tpi.h | 187 ++-- librz/core/cbin.c | 3 +- librz/core/cpdb.c | 114 ++- librz/include/rz_analysis.h | 3 +- librz/include/rz_pdb.h | 19 +- librz/include/rz_util/rz_buf.h | 30 + librz/util/buf.c | 24 + test/db/cmd/cmd_idp | 12 +- test/db/formats/pdb | 128 ++- test/db/tools/rz_bin | 10 +- test/integration/test_pdb.c | 694 +++++++-------- 24 files changed, 1909 insertions(+), 1174 deletions(-) rename librz/analysis/{type_pdb.c => pdb_process.c} (87%) delete mode 100644 librz/bin/pdb/gdata.h create mode 100644 librz/bin/pdb/symbol.c create mode 100644 librz/bin/pdb/symbol.h create mode 100644 librz/bin/pdb/symbol_enum.h diff --git a/librz/analysis/meson.build b/librz/analysis/meson.build index 2c01de8e2f6..25cbcded9c3 100644 --- a/librz/analysis/meson.build +++ b/librz/analysis/meson.build @@ -103,7 +103,7 @@ rz_analysis_sources = [ 'serialize_analysis.c', 'similarity.c', 'switch.c', - 'type_pdb.c', + 'pdb_process.c', 'types.c', 'value.c', 'var.c', diff --git a/librz/analysis/type_pdb.c b/librz/analysis/pdb_process.c similarity index 87% rename from librz/analysis/type_pdb.c rename to librz/analysis/pdb_process.c index 9ab81c037e1..af3e1b10a4c 100644 --- a/librz/analysis/type_pdb.c +++ b/librz/analysis/pdb_process.c @@ -28,7 +28,6 @@ static RzType *parse_enum(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbT static RzTypeEnumCase *parse_enumerate(RzPdbTpiType *type); static bool is_parsable_type(const TpiLeafType type) { - rz_return_val_if_fail(type, false); return (type == LF_STRUCTURE || type == LF_UNION || type == LF_ENUM || @@ -52,7 +51,7 @@ static char *create_type_name_from_offset(ut64 offset) { static RzType *parse_type_array(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type) { rz_return_val_if_fail(type && stream && typedb, NULL); - Tpi_LF_Array *lf_array = type->type_data; + Tpi_LF_Array *lf_array = type->data; RzPdbTpiType *element = rz_bin_pdb_get_type_by_index(stream, lf_array->element_type); if (!element) { return NULL; @@ -73,7 +72,7 @@ static RzType *parse_type_array(const RzTypeDB *typedb, RzPdbTpiStream *stream, static RzType *parse_regular_type(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type, char *name) { rz_return_val_if_fail(type && stream && typedb, NULL); - switch (type->leaf_type) { + switch (type->leaf) { case LF_CLASS: case LF_CLASS_19: // TODO: https://github.com/rizinorg/rizin/issues/1205 @@ -99,7 +98,7 @@ static RzType *parse_regular_type(const RzTypeDB *typedb, RzPdbTpiStream *stream case LF_ENUM: return parse_enum(typedb, stream, type); default: - RZ_LOG_INFO("%s : unsupported leaf type 0x%x\n", __FUNCTION__, type->leaf_type); + RZ_LOG_INFO("%s : unsupported leaf type 0x%x\n", __FUNCTION__, type->leaf); break; } return NULL; @@ -107,11 +106,11 @@ static RzType *parse_regular_type(const RzTypeDB *typedb, RzPdbTpiStream *stream static RzType *parse_type_modifier(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type) { rz_return_val_if_fail(type && stream && typedb, NULL); - Tpi_LF_Modifier *lf_modifier = type->type_data; + Tpi_LF_Modifier *lf_modifier = type->data; RzPdbTpiType *m_utype = rz_bin_pdb_get_type_by_index(stream, lf_modifier->modified_type); if (m_utype) { RzType *typ = parse_type(typedb, stream, m_utype, NULL); - if (typ && lf_modifier->umodifier.bits.const_) { + if (typ && lf_modifier->umodifier.const_) { switch (typ->kind) { case RZ_TYPE_KIND_IDENTIFIER: typ->identifier.is_const = true; @@ -130,7 +129,7 @@ static RzType *parse_type_modifier(const RzTypeDB *typedb, RzPdbTpiStream *strea static RzType *parse_type_pointer(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type, char *name) { rz_return_val_if_fail(type && typedb, NULL); - Tpi_LF_Pointer *lf_pointer = type->type_data; + Tpi_LF_Pointer *lf_pointer = type->data; RzType *typ = RZ_NEW0(RzType); if (!typ) { goto error; @@ -153,8 +152,8 @@ static RzType *parse_type_pointer(const RzTypeDB *typedb, RzPdbTpiStream *stream static RzType *parse_type(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type, char *name) { rz_return_val_if_fail(type && typedb, NULL); RzType *typ; - if (type->leaf_type == LF_SIMPLE_TYPE) { - Tpi_LF_SimpleType *simple_type = type->type_data; + if (type->leaf == LF_SIMPLE_TYPE) { + Tpi_LF_SimpleType *simple_type = type->data; char *error_msg = NULL; typ = rz_type_parse_string_single(typedb->parser, simple_type->type, &error_msg); if (error_msg) { @@ -163,7 +162,7 @@ static RzType *parse_type(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbT } return typ; } else { - if (type->leaf_type == LF_POINTER) { + if (type->leaf == LF_POINTER) { return parse_type_pointer(typedb, stream, type, name); } else { return parse_regular_type(typedb, stream, type, name); @@ -173,7 +172,7 @@ static RzType *parse_type(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbT static void parse_type_arglist(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *arglist, RzPVector /**/ *vec) { rz_return_if_fail(arglist && typedb && vec); - Tpi_LF_Arglist *lf_arglist = arglist->type_data; + Tpi_LF_Arglist *lf_arglist = arglist->data; if (!vec) { return; } @@ -196,7 +195,7 @@ static void parse_type_arglist(const RzTypeDB *typedb, RzPdbTpiStream *stream, R static RzType *parse_type_procedure(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type, char *name) { rz_return_val_if_fail(type && stream && typedb, NULL); - Tpi_LF_Procedure *lf_procedure = type->type_data; + Tpi_LF_Procedure *lf_procedure = type->data; RzType *typ = RZ_NEW0(RzType); RzCallable *callable = RZ_NEW0(RzCallable); if (!typ || !callable) { @@ -207,7 +206,7 @@ static RzType *parse_type_procedure(const RzTypeDB *typedb, RzPdbTpiStream *stre typ->kind = RZ_TYPE_KIND_CALLABLE; typ->callable = callable; if (!name) { - typ->callable->name = create_type_name_from_offset(type->type_index); + typ->callable->name = create_type_name_from_offset(type->index); } else { typ->callable->name = strdup(name); } @@ -237,7 +236,7 @@ static RzType *parse_type_procedure(const RzTypeDB *typedb, RzPdbTpiStream *stre static RzType *parse_type_mfunction(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info, char *name) { rz_return_val_if_fail(type_info && stream && typedb, NULL); - Tpi_LF_MFcuntion *lf_mfunction = type_info->type_data; + Tpi_LF_MFcuntion *lf_mfunction = type_info->data; RzType *type = RZ_NEW0(RzType); RzCallable *callable = RZ_NEW0(RzCallable); if (!type || !callable) { @@ -273,13 +272,13 @@ static RzType *parse_type_mfunction(const RzTypeDB *typedb, RzPdbTpiStream *stre static RzType *parse_type_onemethod(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info) { rz_return_val_if_fail(type_info && typedb, NULL); - Tpi_LF_OneMethod *lf_onemethod = type_info->type_data; + Tpi_LF_OneMethod *lf_onemethod = type_info->data; char *name = rz_bin_pdb_get_type_name(type_info); RzPdbTpiType *utype = rz_bin_pdb_get_type_by_index(stream, lf_onemethod->index); if (!utype) { return NULL; } - if (utype->leaf_type == LF_MFUNCTION) { + if (utype->leaf == LF_MFUNCTION) { return parse_type_mfunction(typedb, stream, utype, name); } return NULL; @@ -287,7 +286,7 @@ static RzType *parse_type_onemethod(const RzTypeDB *typedb, RzPdbTpiStream *stre static RzType *parse_type_member(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info, char *name) { rz_return_val_if_fail(type_info && typedb, NULL); - Tpi_LF_Member *lf_member = type_info->type_data; + Tpi_LF_Member *lf_member = type_info->data; RzPdbTpiType *utype = rz_bin_pdb_get_type_by_index(stream, lf_member->index); if (!utype) { @@ -298,7 +297,7 @@ static RzType *parse_type_member(const RzTypeDB *typedb, RzPdbTpiStream *stream, static RzType *parse_type_static_member(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info, char *name) { rz_return_val_if_fail(type_info && typedb, NULL); - Tpi_LF_StaticMember *lf_stmember = type_info->type_data; + Tpi_LF_StaticMember *lf_stmember = type_info->data; RzPdbTpiType *utype = rz_bin_pdb_get_type_by_index(stream, lf_stmember->index); if (!utype) { return NULL; @@ -308,7 +307,7 @@ static RzType *parse_type_static_member(const RzTypeDB *typedb, RzPdbTpiStream * static RzType *parse_type_nest(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info) { rz_return_val_if_fail(type_info && stream && typedb, NULL); - Tpi_LF_NestType *lf_nest = type_info->type_data; + Tpi_LF_NestType *lf_nest = type_info->data; RzPdbTpiType *utype = rz_bin_pdb_get_type_by_index(stream, lf_nest->index); if (!utype) { return NULL; @@ -356,7 +355,7 @@ static RzTypeStructMember *parse_struct_member(const RzTypeDB *typedb, RzPdbTpiS char *name = NULL; ut64 offset = 0; RzType *type = NULL; - switch (type_info->leaf_type) { + switch (type_info->leaf) { case LF_ONEMETHOD: { name = rz_bin_pdb_get_type_name(type_info); type = parse_type_onemethod(typedb, stream, type_info); @@ -388,7 +387,7 @@ static RzTypeStructMember *parse_struct_member(const RzTypeDB *typedb, RzPdbTpiS // For structure, we don't need vtable for now goto cleanup; default: - RZ_LOG_ERROR("%s : unsupported leaf type 0x%x\n", __FUNCTION__, type_info->leaf_type); + RZ_LOG_ERROR("%s : unsupported leaf type 0x%x\n", __FUNCTION__, type_info->leaf); goto cleanup; } if (!type) { @@ -416,7 +415,7 @@ static inline bool is_tpitype_unnamed(const char *name) { static inline RzBaseType *get_tpitype_basetype(const RzTypeDB *typedb, RzPdbTpiType *type, const char *name) { RzBaseType *base_type; if (is_tpitype_unnamed(name)) { - char *tmp_name = create_type_name_from_offset(type->type_index); + char *tmp_name = create_type_name_from_offset(type->index); base_type = rz_type_db_get_base_type(typedb, tmp_name); free(tmp_name); } else { @@ -432,10 +431,28 @@ static RzType *create_rztype(RzPdbTpiType *type, RzTypeIdentifierKind kind, cons } t->kind = RZ_TYPE_KIND_IDENTIFIER; t->identifier.kind = kind; - t->identifier.name = is_tpitype_unnamed(name) ? create_type_name_from_offset(type->type_index) : strdup(name); + t->identifier.name = is_tpitype_unnamed(name) ? create_type_name_from_offset(type->index) : strdup(name); return t; } +#define PDB_PROCESS_LF_INDEX \ + if (member_info->leaf == LF_INDEX) { \ + ut32 index = rz_bin_pdb_get_type_val(member_info); \ + if (index == type->index) { \ + break; \ + } \ + RzPdbTpiType *t = rz_bin_pdb_get_type_by_index(stream, index); \ + if (!t) { \ + continue; \ + } \ + RzPVector *t_members = rz_bin_pdb_get_type_members(stream, t); \ + if (!t_members) { \ + continue; \ + } \ + members = t_members; \ + goto foreach_members; \ + } + /** * \brief Parses structures into BaseType and saves them into hashtable * @@ -487,19 +504,12 @@ static RzType *parse_structure(const RzTypeDB *typedb, RzPdbTpiStream *stream, R } } rz_vector_clear(&base_type->struct_data.members); - RzList *members = rz_bin_pdb_get_type_members(stream, type); - RzListIter *it; - RzPdbTpiType *member_info; - rz_list_foreach (members, it, member_info) { - if (member_info->leaf_type == LF_INDEX) { - type = rz_bin_pdb_get_type_by_index(stream, rz_bin_pdb_get_type_val(member_info)); - members = rz_bin_pdb_get_type_members(stream, type); - it = rz_list_head(members); - if (!it) { - break; - } - member_info = rz_list_first(members); - } + RzPVector *members = rz_bin_pdb_get_type_members(stream, type); + void **it; +foreach_members: + rz_pvector_foreach (members, it) { + RzPdbTpiType *member_info = *it; + PDB_PROCESS_LF_INDEX; RzTypeStructMember *struct_member = parse_struct_member(typedb, stream, member_info); if (!struct_member) { continue; // skip the failure @@ -533,7 +543,7 @@ static RzTypeUnionMember *parse_union_member(const RzTypeDB *typedb, RzPdbTpiStr char *name = NULL; ut64 offset = 0; RzType *type = NULL; - switch (type_info->leaf_type) { + switch (type_info->leaf) { case LF_ONEMETHOD: { name = rz_bin_pdb_get_type_name(type_info); type = parse_type_onemethod(typedb, stream, type_info); @@ -551,7 +561,7 @@ static RzTypeUnionMember *parse_union_member(const RzTypeDB *typedb, RzPdbTpiStr break; } default: - RZ_LOG_ERROR("%s : unsupported leaf type 0x%x\n", __FUNCTION__, type_info->leaf_type); + RZ_LOG_ERROR("%s : unsupported leaf type 0x%x\n", __FUNCTION__, type_info->leaf); goto cleanup; } if (!type) { @@ -622,19 +632,12 @@ static RzType *parse_union(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdb } } rz_vector_clear(&base_type->union_data.members); - RzList *members = rz_bin_pdb_get_type_members(stream, type); - RzListIter *it; - RzPdbTpiType *member_info; - rz_list_foreach (members, it, member_info) { - if (member_info->leaf_type == LF_INDEX) { - type = rz_bin_pdb_get_type_by_index(stream, rz_bin_pdb_get_type_val(member_info)); - members = rz_bin_pdb_get_type_members(stream, type); - it = rz_list_head(members); - if (!it) { - break; - } - member_info = rz_list_first(members); - } + RzPVector *members = rz_bin_pdb_get_type_members(stream, type); + void **it; +foreach_members: + rz_pvector_foreach (members, it) { + RzPdbTpiType *member_info = *it; + PDB_PROCESS_LF_INDEX; RzTypeUnionMember *union_member = parse_union_member(typedb, stream, member_info); if (!union_member) { continue; // skip the failure @@ -661,7 +664,7 @@ static RzType *parse_union(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdb * \return RzTypeEnumCase* parsed enum case, NULL if fail */ static RzTypeEnumCase *parse_enumerate(RzPdbTpiType *type) { - rz_return_val_if_fail(type && type->leaf_type == LF_ENUMERATE, NULL); + rz_return_val_if_fail(type && type->leaf == LF_ENUMERATE, NULL); char *name = NULL; ut64 value = 0; @@ -688,7 +691,7 @@ static RzTypeEnumCase *parse_enumerate(RzPdbTpiType *type) { */ static RzType *parse_enum(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type) { rz_return_val_if_fail(typedb && type, NULL); - Tpi_LF_Enum *lf_enum = type->type_data; + Tpi_LF_Enum *lf_enum = type->data; // assert all member functions we need info from RzBaseType *base_type = NULL; char *name = rz_bin_pdb_get_type_name(type); @@ -724,7 +727,7 @@ static RzType *parse_enum(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbT rz_type_base_type_free(base_type); return NULL; } - base_type->name = is_tpitype_unnamed(name) ? create_type_name_from_offset(type->type_index) : strdup(name); + base_type->name = is_tpitype_unnamed(name) ? create_type_name_from_offset(type->index) : strdup(name); base_type->size = rz_type_db_get_bitsize(typedb, btype); base_type->type = btype; base_type->attrs = RZ_TYPE_TYPECLASS_INVALID; @@ -737,19 +740,12 @@ static RzType *parse_enum(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbT } } rz_vector_clear(&base_type->enum_data.cases); - RzList *members = rz_bin_pdb_get_type_members(stream, type); - RzListIter *it; - RzPdbTpiType *member_info; - rz_list_foreach (members, it, member_info) { - if (member_info->leaf_type == LF_INDEX) { - type = rz_bin_pdb_get_type_by_index(stream, rz_bin_pdb_get_type_val(member_info)); - members = rz_bin_pdb_get_type_members(stream, type); - it = rz_list_head(members); - if (!it) { - break; - } - member_info = rz_list_first(members); - } + RzPVector *members = rz_bin_pdb_get_type_members(stream, type); + void **it; +foreach_members: + rz_pvector_foreach (members, it) { + RzPdbTpiType *member_info = *it; + PDB_PROCESS_LF_INDEX; RzTypeEnumCase *enum_case = parse_enumerate(member_info); if (!enum_case) { continue; // skip it, move forward @@ -776,29 +772,43 @@ static RzType *parse_enum(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbT * \param stream TPI Stream * \param type Current type */ -static void parse_types(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type) { - rz_return_if_fail(typedb && type); +RZ_API RzType *rz_type_db_pdb_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type) { + rz_return_val_if_fail(typedb && type, NULL); - switch (type->leaf_type) { + switch (type->leaf) { + case LF_SIMPLE_TYPE: { + Tpi_LF_SimpleType *simple_type = type->data; + char *error_msg = NULL; + RzType *typ = rz_type_parse_string_single(typedb->parser, simple_type->type, &error_msg); + if (error_msg) { + RZ_LOG_ERROR("%s : Error parsing complex type member \"%s\" type:\n%s\n", __FUNCTION__, simple_type->type, error_msg); + RZ_FREE(error_msg); + } + return typ; + } case LF_CLASS: case LF_CLASS_19: - break; case LF_STRUCTURE: case LF_STRUCTURE_19: - parse_structure(typedb, stream, type); - break; + return parse_structure(typedb, stream, type); case LF_UNION: - parse_union(typedb, stream, type); - break; + return parse_union(typedb, stream, type); case LF_ENUM: - parse_enum(typedb, stream, type); - break; + return parse_enum(typedb, stream, type); + case LF_MODIFIER: + return parse_type_modifier(typedb, stream, type); + case LF_ARRAY: + return parse_type_array(typedb, stream, type); + case LF_POINTER: + return parse_type_pointer(typedb, stream, type, NULL); + case LF_PROCEDURE: + return parse_type_procedure(typedb, stream, type, NULL); default: - // shouldn't happen, happens when someone modifies leafs that get here - // but not how they should be parsed - RZ_LOG_ERROR("Unknown type record"); + RZ_LOG_DEBUG("Unknown type record: #0x%" PFMT32x ": leaf=0x%" PFMT32x "\n", + type->index, type->leaf); break; } + return NULL; } /** @@ -807,7 +817,7 @@ static void parse_types(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpi * \param t RzTypeDB instance * \param pdb PDB instance */ -RZ_API void rz_parse_pdb_types(const RzTypeDB *typedb, const RzPdb *pdb) { +RZ_API void rz_type_db_pdb_load(const RzTypeDB *typedb, const RzPdb *pdb) { rz_return_if_fail(typedb && pdb); RzPdbTpiStream *stream = pdb->s_tpi; if (!stream) { // no TPI stream found @@ -822,8 +832,8 @@ RZ_API void rz_parse_pdb_types(const RzTypeDB *typedb, const RzPdb *pdb) { RBIter it; RzPdbTpiType *type; rz_rbtree_foreach (stream->types, it, type, RzPdbTpiType, rb) { - if (type && is_parsable_type(type->leaf_type)) { - parse_types(typedb, stream, type); + if (type && is_parsable_type(type->leaf)) { + rz_type_db_pdb_parse(typedb, stream, type); } } } diff --git a/librz/bin/meson.build b/librz/bin/meson.build index db2871431f8..aa03a7389cb 100644 --- a/librz/bin/meson.build +++ b/librz/bin/meson.build @@ -259,6 +259,7 @@ rz_bin_sources = [ 'pdb/pdb_downloader.c', 'pdb/stream_pe.c', 'pdb/tpi.c', + 'pdb/symbol.c', 'dwarf/abbrev.c', 'dwarf/addr.c', diff --git a/librz/bin/pdb/gdata.c b/librz/bin/pdb/gdata.c index 53a919c2491..63a4c350bef 100644 --- a/librz/bin/pdb/gdata.c +++ b/librz/bin/pdb/gdata.c @@ -4,34 +4,12 @@ #include "pdb.h" -static bool parse_gdata_global(GDataGlobal *global, RzBuffer *buf, ut32 initial_seek) { - if (!rz_buf_read_le32(buf, &global->symtype) || - !rz_buf_read_le32(buf, &global->offset)) { - return false; - } - if (!rz_buf_read_le16(buf, &global->segment)) { - return false; - } - if (global->leaf_type == 0x110E) { - global->name = rz_buf_get_string(buf, rz_buf_tell(buf)); - ut16 len = strlen(global->name) + 1; - global->name_len = len; - rz_buf_seek(buf, len, RZ_BUF_CUR); - } else { - if (!rz_buf_read8(buf, &global->name_len)) { - return false; - } - } - ut32 read_len = rz_buf_tell(buf) - initial_seek; - if (read_len % 4) { - ut16 remain = 4 - (read_len % 4); - rz_buf_seek(buf, remain, RZ_BUF_CUR); - } - return true; -} - RZ_IPI bool parse_gdata_stream(RzPdb *pdb, RzPdbMsfStream *stream) { rz_return_val_if_fail(pdb && stream, false); + PDBSymbolTable *syms = pdb_global_symbols(pdb); + if (!syms) { + return false; + } if (!pdb->s_gdata) { pdb->s_gdata = RZ_NEW0(RzPdbGDataStream); } @@ -40,53 +18,38 @@ RZ_IPI bool parse_gdata_stream(RzPdb *pdb, RzPdbMsfStream *stream) { RZ_LOG_ERROR("Error allocating memory.\n"); return false; } - RzBuffer *buf = stream->stream_data; - s->global_list = rz_list_new(); - if (!s->global_list) { + s->global_symbols = rz_pvector_new(free); + if (!s->global_symbols) { return false; } - ut16 len; + + PDBSymbolIter iter = { 0 }; + PDBSymbolTable_iter(syms, &iter); while (true) { - ut32 initial_seek = rz_buf_tell(buf); - if (!rz_buf_read_le16(buf, &len)) { - break; + PDBSymbol *symbol = RZ_NEW0(PDBSymbol); + if (!symbol) { + goto err; } - if (len == 0 || len == UT16_MAX) { + if (!PDBSymbolIter_next(&iter, symbol)) { + free(symbol); break; } - ut16 leaf_type; - if (!rz_buf_read_le16(buf, &leaf_type)) { - return false; - } - if (leaf_type == 0x110E || leaf_type == 0x1009) { - GDataGlobal *global = RZ_NEW0(GDataGlobal); - if (!global) { - goto skip; - } - global->leaf_type = leaf_type; - if (!parse_gdata_global(global, buf, initial_seek)) { - RZ_FREE(global); - return false; - } - rz_list_append(s->global_list, global); + if (!symbol->data) { + free(symbol); continue; } - skip: - rz_buf_seek(buf, len - sizeof(ut16), RZ_BUF_CUR); + rz_pvector_push(s->global_symbols, symbol); } + return true; +err: + return false; } RZ_IPI void free_gdata_stream(RzPdbGDataStream *stream) { if (!stream) { return; } - GDataGlobal *global; - RzListIter *it; - rz_list_foreach (stream->global_list, it, global) { - RZ_FREE(global->name); - RZ_FREE(global); - } - rz_list_free(stream->global_list); + rz_pvector_free(stream->global_symbols); free(stream); } diff --git a/librz/bin/pdb/gdata.h b/librz/bin/pdb/gdata.h deleted file mode 100644 index cab1eeb8b86..00000000000 --- a/librz/bin/pdb/gdata.h +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-FileCopyrightText: 2021 Basstorm -// SPDX-License-Identifier: LGPL-3.0-only - -#ifndef PDB_GDATA_H -#define PDB_GDATA_H - -#include - -typedef struct { - ut16 leaf_type; - ut32 symtype; - ut32 offset; - ut16 segment; - char *name; - ut8 name_len; -} GDataGlobal; - -#endif \ No newline at end of file diff --git a/librz/bin/pdb/omap.c b/librz/bin/pdb/omap.c index 70c41e48f0a..7db2b263e3a 100644 --- a/librz/bin/pdb/omap.c +++ b/librz/bin/pdb/omap.c @@ -52,33 +52,16 @@ RZ_IPI void free_omap_stream(RzPdbOmapStream *stream) { free(stream); } -// inclusive indices -// 0 <= imin when using truncate toward zero divide -// imid = (imin+imax)/2; -// imin unrestricted when using truncate toward minus infinity divide -// imid = (imin+imax)>>1; or -// imid = (int)floor((imin+imax)/2.0); -static int binary_search(unsigned int *A, int key, int imin, int imax) { - int imid; - - // continually narrow search until just one element remains - while (imin < imax) { - imid = (imin + imax) / 2; - if (A[imid] < key) { - imin = imid + 1; - } else { - imax = imid; - } +static int cmp_ut64(const void *pa, const void *pb) { + ut64 a = *(ut64 *)pb; + ut64 b = *(ut64 *)pa; + if (a < b) { + return -1; } - // At exit of while: - // if A[] is empty, then imax < imin - // otherwise imax == imin - - // deferred test for equality - if ((imax == imin) && (A[imin] == key)) { - return imin; + if (a > b) { + return 1; } - return -1; + return 0; } /** @@ -88,21 +71,19 @@ static int binary_search(unsigned int *A, int key, int imin, int imax) { * \param address Where to remap * \return int */ -RZ_API int rz_bin_pdb_omap_remap(RZ_NONNULL RzPdbOmapStream *omap_stream, int address) { +static ut64 pdb_omap_remap(RZ_NONNULL RzPdbOmapStream *omap_stream, ut64 address) { OmapEntry *omap_entry = 0; RzListIter *it = 0; int i = 0; - int pos = 0; - int len = 0; if (!omap_stream) { return address; } - len = rz_list_length(omap_stream->entries); + ut32 len = rz_list_length(omap_stream->entries); if (omap_stream->froms == 0) { - omap_stream->froms = (unsigned int *)malloc(4 * len); + omap_stream->froms = (ut64 *)malloc(sizeof(ut64) * len); if (!omap_stream->froms) { return -1; } @@ -114,17 +95,12 @@ RZ_API int rz_bin_pdb_omap_remap(RZ_NONNULL RzPdbOmapStream *omap_stream, int ad } } - // mb (len -1) ??? - pos = binary_search(omap_stream->froms, address, 0, (len)); - - if (pos == -1) { + const ut64 *p = bsearch(&address, omap_stream->froms, len, sizeof(ut64), cmp_ut64); + if (!p) { return -1; } - if (omap_stream->froms[pos] != address) { - pos -= 1; - } - omap_entry = (OmapEntry *)rz_list_get_n(omap_stream->entries, pos); + omap_entry = (OmapEntry *)rz_list_get_n(omap_stream->entries, *p); if (!omap_entry) { return -1; } @@ -133,3 +109,24 @@ RZ_API int rz_bin_pdb_omap_remap(RZ_NONNULL RzPdbOmapStream *omap_stream, int ad } return omap_entry->to + (address - omap_entry->from); } + +/** + * \brief Convert the section offset to relative virtual address + * + * \param pdb The PDB reference + * \param section_offset The section offset + * \return The relative virtual address + */ +RZ_API ut64 rz_bin_pdb_to_rva(RZ_NONNULL const RzPdb *pdb, const PDBSectionOffset *section_offset) { + static const ut64 DEFAULT = UT64_MAX; + rz_return_val_if_fail(pdb && pdb->s_pe, DEFAULT); + PeImageSectionHeader *section_hdr = pdb_section_hdr_by_index(pdb->s_pe, section_offset->section_index); + if (!section_hdr) { + return DEFAULT; + } + ut64 internal_rva = section_offset->offset + section_hdr->virtual_address; + if (pdb->s_omap) { + return pdb_omap_remap(pdb->s_omap, internal_rva); + } + return internal_rva; +} diff --git a/librz/bin/pdb/pdb.c b/librz/bin/pdb/pdb.c index 0a8409d1a77..135f9b246f1 100644 --- a/librz/bin/pdb/pdb.c +++ b/librz/bin/pdb/pdb.c @@ -44,19 +44,19 @@ static bool parse_streams(RzPdb *pdb) { break; case PDB_STREAM_PDB: if (!parse_pdb_stream(pdb, ms)) { - RZ_LOG_ERROR("Parse pdb stream failed."); + RZ_LOG_ERROR("Parse pdb stream failed.\n"); return false; } break; case PDB_STREAM_TPI: if (!parse_tpi_stream(pdb, ms)) { - RZ_LOG_ERROR("Parse tpi stream failed."); + RZ_LOG_ERROR("Parse tpi stream failed.\n"); return false; } break; case PDB_STREAM_DBI: if (!parse_dbi_stream(pdb, ms)) { - RZ_LOG_ERROR("Parse dbi stream failed."); + RZ_LOG_ERROR("Parse dbi stream failed.\n"); return false; } break; @@ -66,19 +66,19 @@ static bool parse_streams(RzPdb *pdb) { } if (ms->stream_idx == pdb->s_dbi->hdr.sym_record_stream) { if (!parse_gdata_stream(pdb, ms)) { - RZ_LOG_ERROR("Parse gdata stream failed."); + RZ_LOG_ERROR("Parse gdata stream failed.\n"); return false; } } else if (ms->stream_idx == pdb->s_dbi->dbg_hdr.sn_section_hdr || ms->stream_idx == pdb->s_dbi->dbg_hdr.sn_section_hdr_orig) { if (!parse_pe_stream(pdb, ms)) { - RZ_LOG_ERROR("Parse pe stream failed."); + RZ_LOG_ERROR("Parse pe stream failed.\n"); return false; } } else if (ms->stream_idx == pdb->s_dbi->dbg_hdr.sn_omap_to_src || ms->stream_idx == pdb->s_dbi->dbg_hdr.sn_omap_from_src) { if (!parse_omap_stream(pdb, ms)) { - RZ_LOG_ERROR("Parse omap stream failed."); + RZ_LOG_ERROR("Parse omap stream failed.\n"); return false; } } @@ -89,6 +89,36 @@ static bool parse_streams(RzPdb *pdb) { return true; } +RZ_IPI RzPdbMsfStream *pdb_raw_steam(RzPdb *pdb, ut16 index) { + if (!(pdb && pdb->streams)) { + return NULL; + } + RzListIter *it; + RzPdbMsfStream *ms; + rz_list_foreach (pdb->streams, it, ms) { + if (ms->stream_idx == index) { + return ms; + } + } + return NULL; +} + +RZ_IPI PDBSymbolTable *pdb_global_symbols(RzPdb *pdb) { + if (!(pdb && pdb->s_dbi)) { + return NULL; + } + RzPdbMsfStream *steam = pdb_raw_steam(pdb, pdb->s_dbi->hdr.sym_record_stream); + if (!steam) { + return NULL; + } + PDBSymbolTable *symbols = RZ_NEW0(PDBSymbolTable); + if (!symbols) { + return NULL; + } + symbols->b = steam->stream_data; + return symbols; +} + static void msf_stream_free(void *data) { RzPdbMsfStream *msfstream = data; rz_buf_free(msfstream->stream_data); diff --git a/librz/bin/pdb/pdb.h b/librz/bin/pdb/pdb.h index 83e528b5fe2..a7c8f6a0d1d 100644 --- a/librz/bin/pdb/pdb.h +++ b/librz/bin/pdb/pdb.h @@ -1,15 +1,19 @@ // SPDX-FileCopyrightText: 2021 Basstorm // SPDX-License-Identifier: LGPL-3.0-only +#ifndef PDB_PRIVATE_INCLUDE_H_ +#define PDB_PRIVATE_INCLUDE_H_ + #include #include "dbi.h" -#include "gdata.h" #include "omap.h" #include "stream_pe.h" #include "tpi.h" +#include "symbol.h" + +RZ_IPI RzPdbMsfStream *pdb_raw_steam(RzPdb *pdb, ut16 index); +RZ_IPI PDBSymbolTable *pdb_global_symbols(RzPdb *pdb); -#ifndef PDB_PRIVATE_INCLUDE_H_ -#define PDB_PRIVATE_INCLUDE_H_ // OMAP RZ_IPI bool parse_omap_stream(RzPdb *pdb, RzPdbMsfStream *stream); RZ_IPI void free_omap_stream(RzPdbOmapStream *stream); diff --git a/librz/bin/pdb/stream_pe.h b/librz/bin/pdb/stream_pe.h index 30d14ca4ff1..afbfa1b373d 100644 --- a/librz/bin/pdb/stream_pe.h +++ b/librz/bin/pdb/stream_pe.h @@ -26,4 +26,8 @@ typedef struct { ut32 charactestics; } PeImageSectionHeader; +static inline PeImageSectionHeader *pdb_section_hdr_by_index(RZ_NONNULL const RzPdbPeStream *s, ut64 index) { + return rz_list_get_n(s->sections_hdrs, index - 1); +} + #endif \ No newline at end of file diff --git a/librz/bin/pdb/symbol.c b/librz/bin/pdb/symbol.c new file mode 100644 index 00000000000..492196b80bf --- /dev/null +++ b/librz/bin/pdb/symbol.c @@ -0,0 +1,182 @@ +// SPDX-FileCopyrightText: 2023 billow +// SPDX-License-Identifier: LGPL-3.0-only + +#include "symbol.h" + +#define map_err(x) \ + if (!(x)) { \ + goto err; \ + } + +RZ_IPI bool PDBSectionOffset_parse(RzBuffer *b, PDBSectionOffset *section_offset) { + if (!section_offset) { + return false; + } + ut32 offset = 0; + ut16 section_index = 0; + if (!(rz_buf_read_le32(b, &offset) && + rz_buf_read_le16(b, §ion_index))) { + return false; + } + section_offset->section_index = section_index; + section_offset->offset = offset; + return true; +} + +static bool symbol_name_parse(RzBuffer *b, PDBSymbolKind kind, char **result) { + if (kind < S_ST_MAX) { + // TODO: pascal + } else { + return rz_buf_read_string(b, result) > 0; + } + return false; +} + +RZ_IPI bool PDBSData_parse(RzBuffer *b, PDBSymbolKind kind, PDBSData *sdata) { + if (!sdata) { + return false; + } + + if (!(rz_buf_read_le32(b, &sdata->type_index) && + PDBSectionOffset_parse(b, &sdata->offset) && + symbol_name_parse(b, kind, &sdata->name))) { + return false; + } + + switch (kind) { + case S_GMANDATA: + case S_GMANDATA_ST: + sdata->managed = true; + sdata->global = true; + break; + case S_GDATA32: + case S_GDATA32_ST: + sdata->global = true; + break; + case S_LMANDATA: + case S_LMANDATA_ST: + sdata->managed = true; + break; + default: break; + } + return true; +} + +RZ_IPI bool PDBSPublic_parse(RzBuffer *b, PDBSymbolKind kind, PDBSPublic *s) { + map_err(b && s); + ut32 flags = 0; + map_err(rz_buf_read_le32(b, &flags) && + PDBSectionOffset_parse(b, &s->offset) && + symbol_name_parse(b, kind, &s->name)); + s->code = flags & cvpsfCode; + s->function = flags & cvpsfFunction; + s->managed = flags & cvpsfManaged; + s->msil = flags & cvpsfMSIL; + return true; +err: + return false; +} + +RZ_IPI bool PDBSymbol_parse(RzBuffer *b, PDBSymbol *symbol) { + if (!symbol) { + return false; + } + map_err(rz_buf_read_le16(b, &symbol->raw_kind)); + + switch (symbol->raw_kind) { + case S_LDATA32: + case S_LDATA32_ST: + case S_GDATA32: + case S_GDATA32_ST: + case S_LMANDATA: + case S_LMANDATA_ST: + case S_GMANDATA: + case S_GMANDATA_ST: + symbol->kind = PDB_Data; + symbol->data = RZ_NEW0(PDBSData); + map_err(symbol->data); + map_err(PDBSData_parse(b, symbol->raw_kind, symbol->data)); + break; + case S_PUB32: + case S_PUB32_ST: + symbol->kind = PDB_Public; + symbol->data = RZ_NEW0(PDBSPublic); + map_err(symbol->data); + map_err(PDBSPublic_parse(b, symbol->raw_kind, symbol->data)); + break; + default: + RZ_LOG_DEBUG("unimplemented symbol kind: 0x%" PFMT32x "\n", symbol->raw_kind); + break; + } + + return true; +err: + return false; +} + +RZ_IPI bool PDBSymbolTable_iter(PDBSymbolTable *symbol_table, PDBSymbolIter *iter) { + map_err(symbol_table && iter); + iter->b = rz_buf_new_with_buf(symbol_table->b); + return true; +err: + return false; +} + +RZ_IPI PDBSymbol *PDBSymbolTable_symbol_by_index(PDBSymbolTable *symbol_table, PDBSymbolIndex index) { + PDBSymbolIter iter = { 0 }; + map_err(PDBSymbolTable_iter(symbol_table, &iter)); + map_err(PDBSymbolIter_seek(&iter, index)); + PDBSymbol *symbol = RZ_NEW0(PDBSymbol); + map_err(symbol); + map_err(PDBSymbolIter_next(&iter, symbol)); + + return symbol; +err: + return NULL; +} + +RZ_IPI bool PDBSymbolIter_next(PDBSymbolIter *iter, PDBSymbol *symbol) { + if (!iter) { + return false; + } + RzBuffer *b = NULL; + + while (rz_buf_tell(iter->b) < rz_buf_size(iter->b)) { + PDBSymbolIndex index = rz_buf_tell(iter->b); + ut16 length = 0; + map_err(rz_buf_read_le16(iter->b, &length)); + if (length < 2) { + return false; + } + + b = rz_buf_new_slice(iter->b, rz_buf_tell(iter->b), length); + map_err(b); + rz_buf_seek(iter->b, length, RZ_BUF_CUR); + + if (!symbol) { + continue; + } + symbol->index = index; + symbol->length = length; + map_err(PDBSymbol_parse(b, symbol)); + + switch (symbol->raw_kind) { + case S_ALIGN: + case S_SKIP: + continue; + default: + return true; + } + } +err: + rz_buf_free(b); + return false; +} + +RZ_IPI bool PDBSymbolIter_seek(PDBSymbolIter *iter, PDBSymbolIndex index) { + map_err(iter); + rz_buf_seek(iter->b, index, RZ_BUF_SET); + return true; +err: + return false; +} diff --git a/librz/bin/pdb/symbol.h b/librz/bin/pdb/symbol.h new file mode 100644 index 00000000000..89d380b70b2 --- /dev/null +++ b/librz/bin/pdb/symbol.h @@ -0,0 +1,100 @@ +// SPDX-FileCopyrightText: 2023 billow +// SPDX-License-Identifier: LGPL-3.0-only + +#ifndef RIZIN_SYMBOL_H +#define RIZIN_SYMBOL_H + +#include "symbol_enum.h" +#include +#include + +typedef ut16 PDBSymbolKind; +typedef ut32 PDBTypeIndex; +typedef ut32 PDBSymbolIndex; + +RZ_IPI bool PDBSectionOffset_parse(RzBuffer *b, PDBSectionOffset *section_offset); + +typedef struct { + bool global : 1; + bool managed : 1; + PDBTypeIndex type_index; + PDBSectionOffset offset; + char *name; +} PDBSData; + +RZ_IPI bool PDBSData_parse(RzBuffer *b, PDBSymbolKind kind, PDBSData *sdata); + +typedef struct { + bool code : 1; + bool function : 1; + bool managed : 1; + bool msil : 1; + PDBSectionOffset offset; + char *name; +} PDBSPublic; + +RZ_IPI bool PDBSPublic_parse(RzBuffer *b, PDBSymbolKind kind, PDBSPublic *s); + +typedef struct { + PDBSymbolIndex index; + PDBSymbolKind raw_kind; + ut16 length; + enum { + PDB_ScopeEnd, /// End of a scope, such as a procedure. + PDB_ObjName, /// Name of the object file of this module. + PDB_RegisterVariable, /// A Register variable. + PDB_Constant, /// A constant value. + PDB_UserDefinedType, /// A user defined type. + PDB_MultiRegisterVariable, /// A Register variable spanning multiple registers. + PDB_Data, /// Static data, such as a global variable. + PDB_Public, /// A public symbol with a mangled name. + PDB_Procedure, /// A procedure, such as a function or method. + PDB_ThreadStorage, /// A thread local variable. + PDB_CompileFlags, /// Flags used to compile a module. + PDB_UsingNamespace, /// A using namespace directive. + PDB_ProcedureReference, /// Reference to a [`ProcedureSymbol`]. + PDB_DataReference, /// Reference to an imported variable. + PDB_AnnotationReference, /// Reference to an annotation. + PDB_Trampoline, /// Trampoline thunk. + PDB_Export, /// An exported symbol. + PDB_Local, /// A local symbol in optimized code. + PDB_BuildInfo, /// Reference to build information. + PDB_InlineSite, /// The callsite of an inlined function. + PDB_InlineSiteEnd, /// End of an inline callsite. + PDB_ProcedureEnd, /// End of a procedure. + PDB_Label, /// A label. + PDB_Block, /// A block. + PDB_RegisterRelative, /// Data allocated relative to a register. + PDB_Thunk, /// A thunk. + PDB_SeparatedCode, /// A block of separated code. + PDB_DefRange, /// A live range of a variable. + PDB_DefRangeSubField, /// A live range of a sub field of a variable. + PDB_DefRangeRegister, /// A live range of a register variable. + PDB_DefRangeFramePointerRelative, /// A live range of a frame pointer-relative variable. + PDB_DefRangeFramePointerRelativeFullScope, /// A frame-pointer variable which is valid in the full scope of the function. + PDB_DefRangeSubFieldRegister, /// A live range of a sub field of a register variable. + PDB_DefRangeRegisterRelative, /// A live range of a variable related to a register. + PDB_BasePointerRelative, /// A base pointer-relative variable. + PDB_FrameProcedure, /// Extra frame and proc information. + PDB_CallSiteInfo, /// Indirect call site information. + } kind; + void *data; +} PDBSymbol; + +RZ_IPI bool PDBSymbol_parse(RzBuffer *b, PDBSymbol *symbol); + +typedef struct { + RzBuffer *b; +} PDBSymbolTable; + +typedef struct { + RzBuffer *b; +} PDBSymbolIter; + +RZ_IPI bool PDBSymbolTable_iter(PDBSymbolTable *symbol_table, PDBSymbolIter *iter); +RZ_IPI PDBSymbol *PDBSymbolTable_symbol_by_index(PDBSymbolTable *symbol_table, PDBSymbolIndex index); + +RZ_IPI bool PDBSymbolIter_next(PDBSymbolIter *iter, PDBSymbol *symbol); +RZ_IPI bool PDBSymbolIter_seek(PDBSymbolIter *iter, PDBSymbolIndex index); + +#endif // RIZIN_SYMBOL_H diff --git a/librz/bin/pdb/symbol_enum.h b/librz/bin/pdb/symbol_enum.h new file mode 100644 index 00000000000..e7aa079578f --- /dev/null +++ b/librz/bin/pdb/symbol_enum.h @@ -0,0 +1,283 @@ +// SPDX-FileCopyrightText: 2023 billow +// SPDX-License-Identifier: LGPL-3.0-only + +#ifndef RIZIN_SYMBOL_CONSTANTS_H +#define RIZIN_SYMBOL_CONSTANTS_H + +/// A list of known symbol kinds. +/// from: https://github.com/Microsoft/microsoft-pdb/blob/082c5290e5aff028ae84e43affa8be717aa7af73/include/cvinfo.h#L2735 +typedef enum SYM_ENUM_e { + S_COMPILE = 0x0001, // Compile flags symbol + S_REGISTER_16t = 0x0002, // Register variable + S_CONSTANT_16t = 0x0003, // constant symbol + S_UDT_16t = 0x0004, // User defined type + S_SSEARCH = 0x0005, // Start Search + S_END = 0x0006, // Block, procedure, "with" or thunk end + S_SKIP = 0x0007, // Reserve symbol space in $$Symbols table + S_CVRESERVE = 0x0008, // Reserved symbol for CV internal use + S_OBJNAME_ST = 0x0009, // path to object file name + S_ENDARG = 0x000a, // end of argument/return list + S_COBOLUDT_16t = 0x000b, // special UDT for cobol that does not symbol pack + S_MANYREG_16t = 0x000c, // multiple register variable + S_RETURN = 0x000d, // return description symbol + S_ENTRYTHIS = 0x000e, // description of this pointer on entry + + S_BPREL16 = 0x0100, // BP-relative + S_LDATA16 = 0x0101, // Module-local symbol + S_GDATA16 = 0x0102, // Global data symbol + S_PUB16 = 0x0103, // a public symbol + S_LPROC16 = 0x0104, // Local procedure start + S_GPROC16 = 0x0105, // Global procedure start + S_THUNK16 = 0x0106, // Thunk Start + S_BLOCK16 = 0x0107, // block start + S_WITH16 = 0x0108, // with start + S_LABEL16 = 0x0109, // code label + S_CEXMODEL16 = 0x010a, // change execution model + S_VFTABLE16 = 0x010b, // address of virtual function table + S_REGREL16 = 0x010c, // register relative address + + S_BPREL32_16t = 0x0200, // BP-relative + S_LDATA32_16t = 0x0201, // Module-local symbol + S_GDATA32_16t = 0x0202, // Global data symbol + S_PUB32_16t = 0x0203, // a public symbol (CV internal reserved) + S_LPROC32_16t = 0x0204, // Local procedure start + S_GPROC32_16t = 0x0205, // Global procedure start + S_THUNK32_ST = 0x0206, // Thunk Start + S_BLOCK32_ST = 0x0207, // block start + S_WITH32_ST = 0x0208, // with start + S_LABEL32_ST = 0x0209, // code label + S_CEXMODEL32 = 0x020a, // change execution model + S_VFTABLE32_16t = 0x020b, // address of virtual function table + S_REGREL32_16t = 0x020c, // register relative address + S_LTHREAD32_16t = 0x020d, // local thread storage + S_GTHREAD32_16t = 0x020e, // global thread storage + S_SLINK32 = 0x020f, // static link for MIPS EH implementation + + S_LPROCMIPS_16t = 0x0300, // Local procedure start + S_GPROCMIPS_16t = 0x0301, // Global procedure start + + // if these ref symbols have names following then the names are in ST format + S_PROCREF_ST = 0x0400, // Reference to a procedure + S_DATAREF_ST = 0x0401, // Reference to data + S_ALIGN = 0x0402, // Used for page alignment of symbols + + S_LPROCREF_ST = 0x0403, // Local Reference to a procedure + S_OEM = 0x0404, // OEM defined symbol + + // sym records with 32-bit types embedded instead of 16-bit + // all have 0x1000 bit set for easy identification + // only do the 32-bit target versions since we don't really + // care about 16-bit ones anymore. + S_TI16_MAX = 0x1000, + + S_REGISTER_ST = 0x1001, // Register variable + S_CONSTANT_ST = 0x1002, // constant symbol + S_UDT_ST = 0x1003, // User defined type + S_COBOLUDT_ST = 0x1004, // special UDT for cobol that does not symbol pack + S_MANYREG_ST = 0x1005, // multiple register variable + S_BPREL32_ST = 0x1006, // BP-relative + S_LDATA32_ST = 0x1007, // Module-local symbol + S_GDATA32_ST = 0x1008, // Global data symbol + S_PUB32_ST = 0x1009, // a public symbol (CV internal reserved) + S_LPROC32_ST = 0x100a, // Local procedure start + S_GPROC32_ST = 0x100b, // Global procedure start + S_VFTABLE32 = 0x100c, // address of virtual function table + S_REGREL32_ST = 0x100d, // register relative address + S_LTHREAD32_ST = 0x100e, // local thread storage + S_GTHREAD32_ST = 0x100f, // global thread storage + + S_LPROCMIPS_ST = 0x1010, // Local procedure start + S_GPROCMIPS_ST = 0x1011, // Global procedure start + + S_FRAMEPROC = 0x1012, // extra frame and proc information + S_COMPILE2_ST = 0x1013, // extended compile flags and info + + // new symbols necessary for 16-bit enumerates of IA64 registers + // and IA64 specific symbols + + S_MANYREG2_ST = 0x1014, // multiple register variable + S_LPROCIA64_ST = 0x1015, // Local procedure start (IA64) + S_GPROCIA64_ST = 0x1016, // Global procedure start (IA64) + + // Local symbols for IL + S_LOCALSLOT_ST = 0x1017, // local IL sym with field for local slot index + S_PARAMSLOT_ST = 0x1018, // local IL sym with field for parameter slot index + + S_ANNOTATION = 0x1019, // Annotation string literals + + // symbols to support managed code debugging + S_GMANPROC_ST = 0x101a, // Global proc + S_LMANPROC_ST = 0x101b, // Local proc + S_RESERVED1 = 0x101c, // reserved + S_RESERVED2 = 0x101d, // reserved + S_RESERVED3 = 0x101e, // reserved + S_RESERVED4 = 0x101f, // reserved + S_LMANDATA_ST = 0x1020, + S_GMANDATA_ST = 0x1021, + S_MANFRAMEREL_ST = 0x1022, + S_MANREGISTER_ST = 0x1023, + S_MANSLOT_ST = 0x1024, + S_MANMANYREG_ST = 0x1025, + S_MANREGREL_ST = 0x1026, + S_MANMANYREG2_ST = 0x1027, + S_MANTYPREF = 0x1028, // Index for type referenced by name from metadata + S_UNAMESPACE_ST = 0x1029, // Using namespace + + // Symbols w/ SZ name fields. All name fields contain utf8 encoded strings. + S_ST_MAX = 0x1100, // starting point for SZ name symbols + + S_OBJNAME = 0x1101, // path to object file name + S_THUNK32 = 0x1102, // Thunk Start + S_BLOCK32 = 0x1103, // block start + S_WITH32 = 0x1104, // with start + S_LABEL32 = 0x1105, // code label + S_REGISTER = 0x1106, // Register variable + S_CONSTANT = 0x1107, // constant symbol + S_UDT = 0x1108, // User defined type + S_COBOLUDT = 0x1109, // special UDT for cobol that does not symbol pack + S_MANYREG = 0x110a, // multiple register variable + S_BPREL32 = 0x110b, // BP-relative + S_LDATA32 = 0x110c, // Module-local symbol + S_GDATA32 = 0x110d, // Global data symbol + S_PUB32 = 0x110e, // a public symbol (CV internal reserved) + S_LPROC32 = 0x110f, // Local procedure start + S_GPROC32 = 0x1110, // Global procedure start + S_REGREL32 = 0x1111, // register relative address + S_LTHREAD32 = 0x1112, // local thread storage + S_GTHREAD32 = 0x1113, // global thread storage + + S_LPROCMIPS = 0x1114, // Local procedure start + S_GPROCMIPS = 0x1115, // Global procedure start + S_COMPILE2 = 0x1116, // extended compile flags and info + S_MANYREG2 = 0x1117, // multiple register variable + S_LPROCIA64 = 0x1118, // Local procedure start (IA64) + S_GPROCIA64 = 0x1119, // Global procedure start (IA64) + S_LOCALSLOT = 0x111a, // local IL sym with field for local slot index + S_SLOT = S_LOCALSLOT, // alias for LOCALSLOT + S_PARAMSLOT = 0x111b, // local IL sym with field for parameter slot index + + // symbols to support managed code debugging + S_LMANDATA = 0x111c, + S_GMANDATA = 0x111d, + S_MANFRAMEREL = 0x111e, + S_MANREGISTER = 0x111f, + S_MANSLOT = 0x1120, + S_MANMANYREG = 0x1121, + S_MANREGREL = 0x1122, + S_MANMANYREG2 = 0x1123, + S_UNAMESPACE = 0x1124, // Using namespace + + // ref symbols with name fields + S_PROCREF = 0x1125, // Reference to a procedure + S_DATAREF = 0x1126, // Reference to data + S_LPROCREF = 0x1127, // Local Reference to a procedure + S_ANNOTATIONREF = 0x1128, // Reference to an S_ANNOTATION symbol + S_TOKENREF = 0x1129, // Reference to one of the many MANPROCSYM's + + // continuation of managed symbols + S_GMANPROC = 0x112a, // Global proc + S_LMANPROC = 0x112b, // Local proc + + // short, light-weight thunks + S_TRAMPOLINE = 0x112c, // trampoline thunks + S_MANCONSTANT = 0x112d, // constants with metadata type info + + // native attributed local/parms + S_ATTR_FRAMEREL = 0x112e, // relative to virtual frame ptr + S_ATTR_REGISTER = 0x112f, // stored in a register + S_ATTR_REGREL = 0x1130, // relative to register (alternate frame ptr) + S_ATTR_MANYREG = 0x1131, // stored in >1 register + + // Separated code (from the compiler) support + S_SEPCODE = 0x1132, + + S_LOCAL_2005 = 0x1133, // defines a local symbol in optimized code + S_DEFRANGE_2005 = 0x1134, // defines a single range of addresses in which symbol can be evaluated + S_DEFRANGE2_2005 = 0x1135, // defines ranges of addresses in which symbol can be evaluated + + S_SECTION = 0x1136, // A COFF section in a PE executable + S_COFFGROUP = 0x1137, // A COFF group + S_EXPORT = 0x1138, // A export + + S_CALLSITEINFO = 0x1139, // Indirect call site information + S_FRAMECOOKIE = 0x113a, // Security cookie information + + S_DISCARDED = 0x113b, // Discarded by LINK /OPT:REF (experimental, see richards) + + S_COMPILE3 = 0x113c, // Replacement for S_COMPILE2 + S_ENVBLOCK = 0x113d, // Environment block split off from S_COMPILE2 + + S_LOCAL = 0x113e, // defines a local symbol in optimized code + S_DEFRANGE = 0x113f, // defines a single range of addresses in which symbol can be evaluated + S_DEFRANGE_SUBFIELD = 0x1140, // ranges for a subfield + + S_DEFRANGE_REGISTER = 0x1141, // ranges for en-registered symbol + S_DEFRANGE_FRAMEPOINTER_REL = 0x1142, // range for stack symbol. + S_DEFRANGE_SUBFIELD_REGISTER = 0x1143, // ranges for en-registered field of symbol + S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE = 0x1144, // range for stack symbol span valid full scope of function body, gap might apply. + S_DEFRANGE_REGISTER_REL = 0x1145, // range for symbol address as register + offset. + + // S_PROC symbols that reference ID instead of type + S_LPROC32_ID = 0x1146, + S_GPROC32_ID = 0x1147, + S_LPROCMIPS_ID = 0x1148, + S_GPROCMIPS_ID = 0x1149, + S_LPROCIA64_ID = 0x114a, + S_GPROCIA64_ID = 0x114b, + + S_BUILDINFO = 0x114c, // build information. + S_INLINESITE = 0x114d, // inlined function callsite. + S_INLINESITE_END = 0x114e, + S_PROC_ID_END = 0x114f, + + S_DEFRANGE_HLSL = 0x1150, + S_GDATA_HLSL = 0x1151, + S_LDATA_HLSL = 0x1152, + + S_FILESTATIC = 0x1153, + +#if defined(CC_DP_CXX) && CC_DP_CXX + + S_LOCAL_DPC_GROUPSHARED = 0x1154, // DPC groupshared variable + S_LPROC32_DPC = 0x1155, // DPC local procedure start + S_LPROC32_DPC_ID = 0x1156, + S_DEFRANGE_DPC_PTR_TAG = 0x1157, // DPC pointer tag definition range + S_DPC_SYM_TAG_MAP = 0x1158, // DPC pointer tag value to symbol record map + +#endif // CC_DP_CXX + + S_ARMSWITCHTABLE = 0x1159, + S_CALLEES = 0x115a, + S_CALLERS = 0x115b, + S_POGODATA = 0x115c, + S_INLINESITE2 = 0x115d, // extended inline site information + + S_HEAPALLOCSITE = 0x115e, // heap allocation site + + S_MOD_TYPEREF = 0x115f, // only generated at link time + + S_REF_MINIPDB = 0x1160, // only generated at link time for mini PDB + S_PDBMAP = 0x1161, // only generated at link time for mini PDB + + S_GDATA_HLSL32 = 0x1162, + S_LDATA_HLSL32 = 0x1163, + + S_GDATA_HLSL32_EX = 0x1164, + S_LDATA_HLSL32_EX = 0x1165, + + S_RECTYPE_MAX, // one greater than last + S_RECTYPE_LAST = S_RECTYPE_MAX - 1, + S_RECTYPE_PAD = S_RECTYPE_MAX + 0x100 // Used *only* to verify symbol record types so that current PDB code can potentially read + // future PDBs (assuming no format change, etc). + +} SYM_ENUM_e; + +typedef enum CV_PUBSYMFLAGS_e { + cvpsfNone = 0, + cvpsfCode = 0x00000001, + cvpsfFunction = 0x00000002, + cvpsfManaged = 0x00000004, + cvpsfMSIL = 0x00000008, +} CV_PUBSYMFLAGS_e; + +#endif // RIZIN_SYMBOL_CONSTANTS_H diff --git a/librz/bin/pdb/tpi.c b/librz/bin/pdb/tpi.c index 9dee5b60ccc..b3cd9511b1d 100644 --- a/librz/bin/pdb/tpi.c +++ b/librz/bin/pdb/tpi.c @@ -4,8 +4,41 @@ #include "pdb.h" +static RzPdbTpiType *RzPdbTpiType_from_buf(RzBuffer *b, ut32 index, ut16 length); + +static RzBuffer *buf_take(RzBuffer *b, ut32 len) { + RzBuffer *type_buffer = rz_buf_new_slice(b, rz_buf_tell(b), len); + if (!type_buffer) { + return NULL; + } + rz_buf_seek(b, len, RZ_BUF_CUR); + return type_buffer; +} + +static bool buf_empty(RzBuffer *b) { + if (!b) { + return true; + } + return rz_buf_tell(b) >= rz_buf_size(b); +} + +static void buf_read_padding(RzBuffer *b) { + if (!b) { + return; + } + while (!buf_empty(b) && rz_buf_peek(b) > 0xf0) { + ut8 padding = 0; + if (!rz_buf_read8(b, &padding)) { + return; + } + if (padding > 0xf0) { + rz_buf_seek(b, (padding & 0x0f) - 1, RZ_BUF_CUR); + } + } +} + static bool is_simple_type(RzPdbTpiStream *stream, ut32 idx) { - /* https://llvm.org/docs/PDB/RzPdbTpiStream.html#type-indices + /* https://llvm.org/docs/PDB/TpiStream.html#type-indices .---------------------------.------.----------. | Unused | Mode | Kind | '---------------------------'------'----------' @@ -18,7 +51,7 @@ static bool is_simple_type(RzPdbTpiStream *stream, ut32 idx) { int tpi_type_node_cmp(const void *incoming, const RBNode *in_tree, void *user) { ut32 ia = *(ut32 *)incoming; - ut32 ta = container_of(in_tree, const RzPdbTpiType, rb)->type_index; + ut32 ta = container_of(in_tree, const RzPdbTpiType, rb)->index; if (ia < ta) { return -1; } else if (ia > ta) { @@ -80,64 +113,64 @@ static TpiSimpleTypeKind get_simple_type_kind(ut32 type) { } static void parse_codeview_property(TpiCVProperty *p, ut16 value) { - p->bits.packed = GET_BF(value, 0, 1); - p->bits.ctor = GET_BF(value, 1, 1); - p->bits.ovlops = GET_BF(value, 2, 1); - p->bits.isnested = GET_BF(value, 3, 1); - p->bits.packed = GET_BF(value, 4, 1); - p->bits.opassign = GET_BF(value, 5, 1); - p->bits.opcast = GET_BF(value, 6, 1); - p->bits.fwdref = GET_BF(value, 7, 1); - p->bits.scoped = GET_BF(value, 8, 1); - p->bits.hasuniquename = GET_BF(value, 9, 1); - p->bits.sealed = GET_BF(value, 10, 1); - p->bits.hfa = GET_BF(value, 11, 2); - p->bits.intrinsic = GET_BF(value, 13, 1); - p->bits.mocom = GET_BF(value, 14, 2); + p->packed = GET_BF(value, 0, 1); + p->ctor = GET_BF(value, 1, 1); + p->ovlops = GET_BF(value, 2, 1); + p->isnested = GET_BF(value, 3, 1); + p->packed = GET_BF(value, 4, 1); + p->opassign = GET_BF(value, 5, 1); + p->opcast = GET_BF(value, 6, 1); + p->fwdref = GET_BF(value, 7, 1); + p->scoped = GET_BF(value, 8, 1); + p->has_uniquename = GET_BF(value, 9, 1); + p->sealed = GET_BF(value, 10, 1); + p->hfa = GET_BF(value, 11, 2); + p->intrinsic = GET_BF(value, 13, 1); + p->mocom = GET_BF(value, 14, 2); } static void parse_codeview_fld_attribute(TpiCVFldattr *f, ut16 value) { - f->bits.access = GET_BF(value, 0, 2); - f->bits.mprop = GET_BF(value, 2, 3); - f->bits.pseudo = GET_BF(value, 5, 1); - f->bits.noinherit = GET_BF(value, 6, 1); - f->bits.noconstruct = GET_BF(value, 7, 1); - f->bits.compgenx = GET_BF(value, 8, 1); - f->bits.sealed = GET_BF(value, 9, 1); + f->access = GET_BF(value, 0, 2); + f->mprop = GET_BF(value, 2, 3); + f->pseudo = GET_BF(value, 5, 1); + f->noinherit = GET_BF(value, 6, 1); + f->noconstruct = GET_BF(value, 7, 1); + f->compgenx = GET_BF(value, 8, 1); + f->sealed = GET_BF(value, 9, 1); } static void parse_codeview_func_attribute(TpiCVFuncattr *f, ut8 value) { - f->bits.cxxreturnudt = GET_BF(value, 0, 1); - f->bits.ctor = GET_BF(value, 1, 1); - f->bits.ctorvbase = GET_BF(value, 2, 1); + f->cxxreturnudt = GET_BF(value, 0, 1); + f->ctor = GET_BF(value, 1, 1); + f->ctorvbase = GET_BF(value, 2, 1); } static void parse_codeview_pointer_attribute(TpiCVPointerAttr *p, ut32 value) { - p->bits.ptrtype = GET_BF(value, 0, 5); - p->bits.ptrmode = GET_BF(value, 5, 3); - p->bits.flat32 = GET_BF(value, 8, 1); - p->bits.volatile_ = GET_BF(value, 9, 1); - p->bits.const_ = GET_BF(value, 10, 1); - p->bits.unaligned = GET_BF(value, 11, 1); - p->bits.restrict_ = GET_BF(value, 12, 1); - p->bits.size = GET_BF(value, 13, 6); - p->bits.mocom = GET_BF(value, 19, 1); - p->bits.lref = GET_BF(value, 20, 1); - p->bits.rref = GET_BF(value, 21, 1); - p->bits.unused = GET_BF(value, 22, 10); + p->ptrtype = GET_BF(value, 0, 5); + p->ptrmode = GET_BF(value, 5, 3); + p->flat32 = GET_BF(value, 8, 1); + p->volatile_ = GET_BF(value, 9, 1); + p->const_ = GET_BF(value, 10, 1); + p->unaligned = GET_BF(value, 11, 1); + p->restrict_ = GET_BF(value, 12, 1); + p->size = GET_BF(value, 13, 6); + p->mocom = GET_BF(value, 19, 1); + p->lref = GET_BF(value, 20, 1); + p->rref = GET_BF(value, 21, 1); + p->unused = GET_BF(value, 22, 10); } static void parse_codeview_modifier(TpiCVModifier *m, ut16 value) { - m->bits.const_ = GET_BF(value, 0, 1); - m->bits.volatile_ = GET_BF(value, 1, 1); - m->bits.unaligned = GET_BF(value, 2, 1); + m->const_ = GET_BF(value, 0, 1); + m->volatile_ = GET_BF(value, 1, 1); + m->unaligned = GET_BF(value, 2, 1); } /** * \brief Parses simple type if the idx represents one * \param RzPdbTpiStream TPI stream context * \param idx leaf index - * \return RzPdbTpiType, leaf_type = 0 -> error + * \return RzPdbTpiType, leaf = 0 -> error */ RZ_IPI RzPdbTpiType *parse_simple_type(RzPdbTpiStream *stream, ut32 idx) { RzPdbTpiType *type = RZ_NEW0(RzPdbTpiType); @@ -145,8 +178,8 @@ RZ_IPI RzPdbTpiType *parse_simple_type(RzPdbTpiStream *stream, ut32 idx) { RZ_LOG_ERROR("Error allocating memory.\n"); return NULL; } - type->leaf_type = LF_SIMPLE_TYPE; - type->type_index = idx; + type->leaf = LF_SIMPLE_TYPE; + type->index = idx; // For simple type we don't set length type->length = 0; Tpi_LF_SimpleType *simple_type = RZ_NEW0(Tpi_LF_SimpleType); @@ -155,7 +188,7 @@ RZ_IPI RzPdbTpiType *parse_simple_type(RzPdbTpiStream *stream, ut32 idx) { free(type); return NULL; } - type->type_data = simple_type; + type->data = simple_type; RzStrBuf *buf; TpiSimpleTypeKind kind = get_simple_type_kind(idx); switch (kind) { @@ -336,10 +369,18 @@ RZ_IPI RzPdbTpiType *parse_simple_type(RzPdbTpiStream *stream, ut32 idx) { } simple_type->type = rz_strbuf_drain(buf); // We just insert once - rz_rbtree_insert(&stream->types, &type->type_index, &type->rb, tpi_type_node_cmp, NULL); + rz_rbtree_insert(&stream->types, &type->index, &type->rb, tpi_type_node_cmp, NULL); return type; } +static void simple_type_free(Tpi_LF_SimpleType *t) { + if (!t) { + return; + } + free(t->type); + free(t); +} + static ut64 get_numeric_val(Tpi_Type_Numeric *numeric) { switch (numeric->type_index) { case LF_CHAR: @@ -371,24 +412,24 @@ static ut64 get_numeric_val(Tpi_Type_Numeric *numeric) { */ RZ_API bool rz_bin_pdb_type_is_fwdref(RZ_NONNULL RzPdbTpiType *t) { rz_return_val_if_fail(t, false); // return val stands for we do nothing for it - switch (t->leaf_type) { + switch (t->leaf) { case LF_UNION: { - Tpi_LF_Union *lf = (Tpi_LF_Union *)t->type_data; - return lf->prop.bits.fwdref ? true : false; + Tpi_LF_Union *lf = (Tpi_LF_Union *)t->data; + return lf->prop.fwdref ? true : false; } case LF_STRUCTURE: case LF_CLASS: { - Tpi_LF_Structure *lf = (Tpi_LF_Structure *)t->type_data; - return lf->prop.bits.fwdref ? true : false; + Tpi_LF_Structure *lf = (Tpi_LF_Structure *)t->data; + return lf->prop.fwdref ? true : false; } case LF_STRUCTURE_19: case LF_CLASS_19: { - Tpi_LF_Structure_19 *lf = (Tpi_LF_Structure_19 *)t->type_data; - return lf->prop.bits.fwdref ? true : false; + Tpi_LF_Structure_19 *lf = (Tpi_LF_Structure_19 *)t->data; + return lf->prop.fwdref ? true : false; } case LF_ENUM: { - Tpi_LF_Enum *lf = (Tpi_LF_Enum *)t->type_data; - return lf->prop.bits.fwdref ? true : false; + Tpi_LF_Enum *lf = (Tpi_LF_Enum *)t->data; + return lf->prop.fwdref ? true : false; } default: rz_warn_if_reached(); @@ -397,40 +438,41 @@ RZ_API bool rz_bin_pdb_type_is_fwdref(RZ_NONNULL RzPdbTpiType *t) { } /** - * \brief Get the RzPdbTpiType member list + * \brief Get the RzPdbTpiType members * * \param stream TPI stream * \param t RzPdbTpiType - * \return RzList * + * \return RzPVector * */ -RZ_API RZ_BORROW RzList /**/ *rz_bin_pdb_get_type_members(RZ_NONNULL RzPdbTpiStream *stream, RzPdbTpiType *t) { +RZ_API RZ_BORROW RzPVector /**/ *rz_bin_pdb_get_type_members( + RZ_NONNULL RzPdbTpiStream *stream, RzPdbTpiType *t) { rz_return_val_if_fail(t, NULL); RzPdbTpiType *tmp; - switch (t->leaf_type) { + switch (t->leaf) { case LF_FIELDLIST: { - Tpi_LF_FieldList *lf = t->type_data; + Tpi_LF_FieldList *lf = t->data; return lf->substructs; } case LF_UNION: { - tmp = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Union *)t->type_data)->field_list); - Tpi_LF_FieldList *lf_union = tmp ? tmp->type_data : NULL; + tmp = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Union *)t->data)->field_list); + Tpi_LF_FieldList *lf_union = tmp ? tmp->data : NULL; return lf_union ? lf_union->substructs : NULL; } case LF_STRUCTURE: case LF_CLASS: { - tmp = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Structure *)t->type_data)->field_list); - Tpi_LF_FieldList *lf_struct = tmp ? tmp->type_data : NULL; + tmp = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Structure *)t->data)->field_list); + Tpi_LF_FieldList *lf_struct = tmp ? tmp->data : NULL; return lf_struct ? lf_struct->substructs : NULL; } case LF_STRUCTURE_19: case LF_CLASS_19: { - tmp = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Structure_19 *)t->type_data)->field_list); - Tpi_LF_FieldList *lf_struct19 = tmp ? tmp->type_data : NULL; + tmp = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Structure_19 *)t->data)->field_list); + Tpi_LF_FieldList *lf_struct19 = tmp ? tmp->data : NULL; return lf_struct19 ? lf_struct19->substructs : NULL; } case LF_ENUM: { - tmp = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Enum *)t->type_data)->field_list); - Tpi_LF_FieldList *lf_enum = tmp ? tmp->type_data : NULL; + tmp = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Enum *)t->data)->field_list); + Tpi_LF_FieldList *lf_enum = tmp ? tmp->data : NULL; return lf_enum ? lf_enum->substructs : NULL; } default: @@ -446,51 +488,51 @@ RZ_API RZ_BORROW RzList /**/ *rz_bin_pdb_get_type_members(RZ_NON */ RZ_API RZ_BORROW char *rz_bin_pdb_get_type_name(RZ_NONNULL RzPdbTpiType *type) { rz_return_val_if_fail(type, NULL); - switch (type->leaf_type) { + switch (type->leaf) { case LF_MEMBER: { - Tpi_LF_Member *lf_member = type->type_data; + Tpi_LF_Member *lf_member = type->data; return lf_member->name.name; } case LF_STMEMBER: { - Tpi_LF_StaticMember *lf_stmember = type->type_data; + Tpi_LF_StaticMember *lf_stmember = type->data; return lf_stmember->name.name; } case LF_ONEMETHOD: { - Tpi_LF_OneMethod *lf_onemethod = type->type_data; + Tpi_LF_OneMethod *lf_onemethod = type->data; return lf_onemethod->name.name; } case LF_METHOD: { - Tpi_LF_Method *lf_method = type->type_data; + Tpi_LF_Method *lf_method = type->data; return lf_method->name.name; } case LF_NESTTYPE: { - Tpi_LF_NestType *lf_nesttype = type->type_data; + Tpi_LF_NestType *lf_nesttype = type->data; return lf_nesttype->name.name; } case LF_ENUM: { - Tpi_LF_Enum *lf_enum = type->type_data; + Tpi_LF_Enum *lf_enum = type->data; return lf_enum->name.name; } case LF_ENUMERATE: { - Tpi_LF_Enumerate *lf_enumerate = type->type_data; + Tpi_LF_Enumerate *lf_enumerate = type->data; return lf_enumerate->name.name; } case LF_CLASS: case LF_STRUCTURE: { - Tpi_LF_Structure *lf_struct = type->type_data; + Tpi_LF_Structure *lf_struct = type->data; return lf_struct->name.name; } case LF_CLASS_19: case LF_STRUCTURE_19: { - Tpi_LF_Structure_19 *lf_struct_19 = type->type_data; + Tpi_LF_Structure_19 *lf_struct_19 = type->data; return lf_struct_19->name.name; } case LF_ARRAY: { - Tpi_LF_Array *lf_array = type->type_data; + Tpi_LF_Array *lf_array = type->data; return lf_array->name.name; } case LF_UNION: { - Tpi_LF_Union *lf_union = type->type_data; + Tpi_LF_Union *lf_union = type->data; return lf_union->name.name; } default: @@ -506,39 +548,39 @@ RZ_API RZ_BORROW char *rz_bin_pdb_get_type_name(RZ_NONNULL RzPdbTpiType *type) { */ RZ_API ut64 rz_bin_pdb_get_type_val(RZ_NONNULL RzPdbTpiType *type) { rz_return_val_if_fail(type, -1); - switch (type->leaf_type) { + switch (type->leaf) { case LF_ONEMETHOD: { - Tpi_LF_OneMethod *lf_onemethod = type->type_data; + Tpi_LF_OneMethod *lf_onemethod = type->data; return lf_onemethod->offset_in_vtable; } case LF_MEMBER: { - Tpi_LF_Member *lf_member = type->type_data; + Tpi_LF_Member *lf_member = type->data; return get_numeric_val(&lf_member->offset); } case LF_ENUMERATE: { - Tpi_LF_Enumerate *lf_enumerate = type->type_data; + Tpi_LF_Enumerate *lf_enumerate = type->data; return get_numeric_val(&lf_enumerate->enum_value); } case LF_CLASS: case LF_STRUCTURE: { - Tpi_LF_Structure *lf_struct = type->type_data; + Tpi_LF_Structure *lf_struct = type->data; return get_numeric_val(&lf_struct->size); } case LF_CLASS_19: case LF_STRUCTURE_19: { - Tpi_LF_Structure_19 *lf_struct_19 = type->type_data; + Tpi_LF_Structure_19 *lf_struct_19 = type->data; return get_numeric_val(&lf_struct_19->size); } case LF_ARRAY: { - Tpi_LF_Array *lf_array = type->type_data; + Tpi_LF_Array *lf_array = type->data; return get_numeric_val(&lf_array->size); } case LF_UNION: { - Tpi_LF_Union *lf_union = type->type_data; + Tpi_LF_Union *lf_union = type->data; return get_numeric_val(&lf_union->size); } case LF_INDEX: { - Tpi_LF_Index *lf_index = type->type_data; + Tpi_LF_Index *lf_index = type->data; return lf_index->index; } default: @@ -569,42 +611,42 @@ static void free_snumeric(Tpi_Type_Numeric *numeric) { static void free_tpi_type(void *type_info) { rz_return_if_fail(type_info); RzPdbTpiType *type = (RzPdbTpiType *)type_info; - switch (type->leaf_type) { + switch (type->leaf) { case LF_ENUMERATE: { - Tpi_LF_Enumerate *lf_en = (Tpi_LF_Enumerate *)type->type_data; + Tpi_LF_Enumerate *lf_en = (Tpi_LF_Enumerate *)type->data; free_snumeric(&(lf_en->enum_value)); RZ_FREE(lf_en->name.name); break; } case LF_NESTTYPE: { - Tpi_LF_NestType *lf_nest = (Tpi_LF_NestType *)type->type_data; + Tpi_LF_NestType *lf_nest = (Tpi_LF_NestType *)type->data; RZ_FREE(lf_nest->name.name); break; } case LF_METHOD: { - Tpi_LF_Method *lf_meth = (Tpi_LF_Method *)type->type_data; + Tpi_LF_Method *lf_meth = (Tpi_LF_Method *)type->data; RZ_FREE(lf_meth->name.name); break; } case LF_MEMBER: { - Tpi_LF_Member *lf_mem = (Tpi_LF_Member *)type->type_data; + Tpi_LF_Member *lf_mem = (Tpi_LF_Member *)type->data; free_snumeric(&lf_mem->offset); RZ_FREE(lf_mem->name.name); break; } case LF_STMEMBER: { - Tpi_LF_StaticMember *lf_stmem = (Tpi_LF_StaticMember *)type->type_data; + Tpi_LF_StaticMember *lf_stmem = (Tpi_LF_StaticMember *)type->data; RZ_FREE(lf_stmem->name.name); break; } case LF_FIELDLIST: { - Tpi_LF_FieldList *lf_fieldlist = (Tpi_LF_FieldList *)type->type_data; - rz_list_free(lf_fieldlist->substructs); + Tpi_LF_FieldList *lf_fieldlist = (Tpi_LF_FieldList *)type->data; + rz_pvector_free(lf_fieldlist->substructs); break; } case LF_CLASS: case LF_STRUCTURE: { - Tpi_LF_Structure *lf_class = (Tpi_LF_Structure *)type->type_data; + Tpi_LF_Structure *lf_class = (Tpi_LF_Structure *)type->data; free_snumeric(&lf_class->size); RZ_FREE(lf_class->name.name); RZ_FREE(lf_class->mangled_name.name); @@ -612,87 +654,94 @@ static void free_tpi_type(void *type_info) { } case LF_CLASS_19: case LF_STRUCTURE_19: { - Tpi_LF_Structure_19 *lf_class_19 = (Tpi_LF_Structure_19 *)type->type_data; + Tpi_LF_Structure_19 *lf_class_19 = (Tpi_LF_Structure_19 *)type->data; free_snumeric(&lf_class_19->size); RZ_FREE(lf_class_19->name.name); RZ_FREE(lf_class_19->mangled_name.name); break; } case LF_UNION: { - Tpi_LF_Union *lf_union = (Tpi_LF_Union *)type->type_data; + Tpi_LF_Union *lf_union = (Tpi_LF_Union *)type->data; free_snumeric(&lf_union->size); RZ_FREE(lf_union->name.name); RZ_FREE(lf_union->mangled_name.name); break; } case LF_ONEMETHOD: { - Tpi_LF_OneMethod *lf_onemethod = (Tpi_LF_OneMethod *)type->type_data; + Tpi_LF_OneMethod *lf_onemethod = (Tpi_LF_OneMethod *)type->data; RZ_FREE(lf_onemethod->name.name); break; } case LF_BCLASS: { - Tpi_LF_BClass *lf_bclass = (Tpi_LF_BClass *)type->type_data; + Tpi_LF_BClass *lf_bclass = (Tpi_LF_BClass *)type->data; free_snumeric(&lf_bclass->offset); break; } case LF_VBCLASS: case LF_IVBCLASS: { - Tpi_LF_VBClass *lf_vbclass = (Tpi_LF_VBClass *)type->type_data; + Tpi_LF_VBClass *lf_vbclass = (Tpi_LF_VBClass *)type->data; free_snumeric(&lf_vbclass->vb_pointer_offset); free_snumeric(&lf_vbclass->vb_offset_from_vbtable); break; } case LF_ENUM: { - Tpi_LF_Enum *lf_enum = (Tpi_LF_Enum *)type->type_data; + Tpi_LF_Enum *lf_enum = (Tpi_LF_Enum *)type->data; RZ_FREE(lf_enum->name.name); RZ_FREE(lf_enum->mangled_name.name); break; } case LF_ARRAY: { - Tpi_LF_Array *lf_array = (Tpi_LF_Array *)type->type_data; + Tpi_LF_Array *lf_array = (Tpi_LF_Array *)type->data; free_snumeric(&lf_array->size); RZ_FREE(lf_array->name.name); break; } case LF_ARGLIST: { - Tpi_LF_Arglist *lf_arglist = (Tpi_LF_Arglist *)type->type_data; + Tpi_LF_Arglist *lf_arglist = (Tpi_LF_Arglist *)type->data; RZ_FREE(lf_arglist->arg_type); break; } case LF_VTSHAPE: { - Tpi_LF_Vtshape *lf_vtshape = (Tpi_LF_Vtshape *)type->type_data; + Tpi_LF_Vtshape *lf_vtshape = (Tpi_LF_Vtshape *)type->data; RZ_FREE(lf_vtshape->vt_descriptors); break; } case LF_SIMPLE_TYPE: { - Tpi_LF_SimpleType *lf_simple = (Tpi_LF_SimpleType *)type->type_data; + Tpi_LF_SimpleType *lf_simple = (Tpi_LF_SimpleType *)type->data; RZ_FREE(lf_simple->type); break; } case LF_METHODLIST: { - Tpi_LF_MethodList *lf_mlist = (Tpi_LF_MethodList *)type->type_data; + Tpi_LF_MethodList *lf_mlist = (Tpi_LF_MethodList *)type->data; rz_list_free(lf_mlist->members); break; } - case LF_POINTER: + case LF_VFTABLE: { + Tpi_LF_Vftable *vft = type->data; + rz_pvector_fini(&vft->method_names); break; + } + case LF_POINTER: case LF_PROCEDURE: - break; case LF_MODIFIER: - break; case LF_MFUNCTION: - break; case LF_BITFIELD: - break; case LF_INDEX: - break; case LF_VFUNCTAB: + case LF_LABEL: + break; + case 0: + if (type->index < 0x1000) { + simple_type_free(type->data); + } break; default: - rz_warn_if_reached(); + if (type->data) { + rz_warn_if_reached(); + } break; } - free(type->type_data); + free(type->data); free(type); } @@ -711,45 +760,12 @@ RZ_IPI void free_tpi_stream(RzPdbTpiStream *stream) { free(stream); } -static void skip_padding(RzBuffer *buf, ut16 len, ut16 *read_len, bool has_length) { - while (*read_len < len) { - ut8 byt; - if (!rz_buf_read8(buf, &byt)) { - break; - } - if (has_length && ((byt & 0xf0) == 0xf0 || byt == 0)) { - *read_len += 1; - } else if ((byt & 0xf0) == 0xf0) { - *read_len += 1; - } else { - rz_buf_seek(buf, -1, RZ_BUF_CUR); - break; - } - } -} - -static bool has_non_padding(RzBuffer *buf, ut16 len, ut16 *read_len) { - while (*read_len < len) { - ut8 byt; - if (!rz_buf_read8(buf, &byt)) { - break; - } - rz_buf_seek(buf, -1, RZ_BUF_CUR); - if ((byt & 0xf0) != 0xf0) { - return true; - } - return false; - } - return false; -} - -static bool parse_type_numeric(RzBuffer *buf, Tpi_Type_Numeric *numeric, ut16 *read_len) { +static bool parse_type_numeric(RzBuffer *buf, Tpi_Type_Numeric *numeric) { numeric->data = 0; numeric->is_integer = true; if (!rz_buf_read_le16(buf, &numeric->type_index)) { return false; } - *read_len += sizeof(ut16); switch (numeric->type_index) { case LF_CHAR: numeric->data = RZ_NEW0(st8); @@ -757,7 +773,6 @@ static bool parse_type_numeric(RzBuffer *buf, Tpi_Type_Numeric *numeric, ut16 *r RZ_FREE(numeric->data); return false; } - *read_len += sizeof(st8); break; case LF_SHORT: numeric->data = RZ_NEW0(st16); @@ -765,7 +780,6 @@ static bool parse_type_numeric(RzBuffer *buf, Tpi_Type_Numeric *numeric, ut16 *r RZ_FREE(numeric->data); return false; } - *read_len += sizeof(st16); break; case LF_USHORT: numeric->data = RZ_NEW0(ut16); @@ -773,7 +787,6 @@ static bool parse_type_numeric(RzBuffer *buf, Tpi_Type_Numeric *numeric, ut16 *r RZ_FREE(numeric->data); return false; } - *read_len += sizeof(ut16); break; case LF_LONG: numeric->data = RZ_NEW0(st32); @@ -781,7 +794,6 @@ static bool parse_type_numeric(RzBuffer *buf, Tpi_Type_Numeric *numeric, ut16 *r RZ_FREE(numeric->data); return false; } - *read_len += sizeof(st32); break; case LF_ULONG: numeric->data = RZ_NEW0(ut32); @@ -789,7 +801,6 @@ static bool parse_type_numeric(RzBuffer *buf, Tpi_Type_Numeric *numeric, ut16 *r RZ_FREE(numeric->data); return false; } - *read_len += sizeof(ut32); break; case LF_QUADWORD: numeric->data = RZ_NEW0(st64); @@ -797,7 +808,6 @@ static bool parse_type_numeric(RzBuffer *buf, Tpi_Type_Numeric *numeric, ut16 *r RZ_FREE(numeric->data); return false; } - *read_len += sizeof(st64); break; case LF_UQUADWORD: numeric->data = RZ_NEW0(ut64); @@ -805,7 +815,6 @@ static bool parse_type_numeric(RzBuffer *buf, Tpi_Type_Numeric *numeric, ut16 *r RZ_FREE(numeric->data); return false; } - *read_len += sizeof(ut64); break; default: if (numeric->type_index >= 0x8000) { @@ -821,31 +830,11 @@ static bool parse_type_numeric(RzBuffer *buf, Tpi_Type_Numeric *numeric, ut16 *r return true; } -static void parse_type_string(RzBuffer *buf, Tpi_Type_String *str, ut16 len, ut16 *read_len) { - ut16 size = 0; - while (*read_len < len) { - ut8 byt; - if (!rz_buf_read8(buf, &byt)) { - break; - } - *(read_len) += 1; - size++; - if (!byt) { - rz_buf_seek(buf, -size, RZ_BUF_CUR); - str->name = (char *)rz_mem_alloc(size); - if (!str->name) { - str->name = NULL; - RZ_LOG_ERROR("Error allocating memory.\n"); - return; - } - rz_buf_read(buf, (ut8 *)str->name, size); - str->size = size; - break; - } - } +static void parse_type_string(RzBuffer *buf, Tpi_Type_String *str) { + str->size = rz_buf_read_string(buf, &str->name); } -static Tpi_LF_Enumerate *parse_type_enumerate(RzBuffer *buf, ut16 len, ut16 *read_len) { +static Tpi_LF_Enumerate *parse_type_enumerate(RzBuffer *buf) { rz_return_val_if_fail(buf, NULL); Tpi_LF_Enumerate *enumerate = RZ_NEW0(Tpi_LF_Enumerate); if (!enumerate) { @@ -857,8 +846,7 @@ static Tpi_LF_Enumerate *parse_type_enumerate(RzBuffer *buf, ut16 len, ut16 *rea return NULL; } parse_codeview_fld_attribute(&enumerate->fldattr, fldattr); - *read_len += sizeof(ut16); - if (!parse_type_numeric(buf, &enumerate->enum_value, read_len)) { + if (!parse_type_numeric(buf, &enumerate->enum_value)) { RZ_FREE(enumerate); return NULL; } @@ -868,34 +856,32 @@ static Tpi_LF_Enumerate *parse_type_enumerate(RzBuffer *buf, ut16 len, ut16 *rea RZ_FREE(enumerate); return NULL; } - parse_type_string(buf, &enumerate->name, len, read_len); - skip_padding(buf, len, read_len, false); + parse_type_string(buf, &enumerate->name); return enumerate; } -static Tpi_LF_Index *parse_type_index(RzBuffer *buf, ut16 len, ut16 *read_len) { - rz_return_val_if_fail(buf, NULL); +static Tpi_LF_Index *parse_type_index(RzBuffer *b) { + rz_return_val_if_fail(b, NULL); Tpi_LF_Index *index = RZ_NEW0(Tpi_LF_Index); if (!index) { return NULL; } - ut16 fldattr; - if (!rz_buf_read_le16(buf, &fldattr)) { - RZ_FREE(index); - return NULL; + if (!(rz_buf_read_le16(b, &index->pad0) && + rz_buf_read_le32(b, &index->index))) { + goto err; } - parse_codeview_fld_attribute(&index->fldattr, fldattr); - *read_len += sizeof(ut16); - if (!rz_buf_read_le32(buf, &index->index)) { - RZ_FREE(index); - return NULL; + if (index->pad0 != 0) { + RZ_LOG_ERROR("LF_Index pad0 must be 0\n"); + goto err; } - *read_len += sizeof(ut32); - skip_padding(buf, len, read_len, false); + index->leaf = LF_INDEX; return index; +err: + free(index); + return NULL; } -static Tpi_LF_NestType *parse_type_nesttype(RzBuffer *buf, ut16 len, ut16 *read_len) { +static Tpi_LF_NestType *parse_type_nesttype(RzBuffer *buf) { rz_return_val_if_fail(buf, NULL); Tpi_LF_NestType *nest = RZ_NEW0(Tpi_LF_NestType); if (!nest) { @@ -905,18 +891,15 @@ static Tpi_LF_NestType *parse_type_nesttype(RzBuffer *buf, ut16 len, ut16 *read_ RZ_FREE(nest); return NULL; } - *read_len += sizeof(ut16); if (!rz_buf_read_le32(buf, &nest->index)) { RZ_FREE(nest); return NULL; } - *read_len += sizeof(ut32); - parse_type_string(buf, &nest->name, len, read_len); - skip_padding(buf, len, read_len, false); + parse_type_string(buf, &nest->name); return nest; } -static Tpi_LF_VFuncTab *parse_type_vfunctab(RzBuffer *buf, ut16 len, ut16 *read_len) { +static Tpi_LF_VFuncTab *parse_type_vfunctab(RzBuffer *buf) { rz_return_val_if_fail(buf, NULL); Tpi_LF_VFuncTab *vftab = RZ_NEW0(Tpi_LF_VFuncTab); if (!vftab) { @@ -926,16 +909,14 @@ static Tpi_LF_VFuncTab *parse_type_vfunctab(RzBuffer *buf, ut16 len, ut16 *read_ RZ_FREE(vftab); return NULL; } - *read_len += sizeof(ut16); if (!rz_buf_read_le32(buf, &vftab->index)) { RZ_FREE(vftab); return NULL; } - *read_len += sizeof(ut32); return vftab; } -static Tpi_LF_Method *parse_type_method(RzBuffer *buf, ut16 len, ut16 *read_len) { +static Tpi_LF_Method *parse_type_method(RzBuffer *buf) { rz_return_val_if_fail(buf, NULL); Tpi_LF_Method *method = RZ_NEW0(Tpi_LF_Method); if (!method) { @@ -945,18 +926,15 @@ static Tpi_LF_Method *parse_type_method(RzBuffer *buf, ut16 len, ut16 *read_len) RZ_FREE(method); return NULL; } - *read_len += sizeof(ut16); if (!rz_buf_read_le32(buf, &method->mlist)) { RZ_FREE(method); return NULL; } - *read_len += sizeof(ut32); - parse_type_string(buf, &method->name, len, read_len); - skip_padding(buf, len, read_len, false); + parse_type_string(buf, &method->name); return method; } -static Tpi_LF_Member *parse_type_member(RzBuffer *buf, ut16 len, ut16 *read_len) { +static Tpi_LF_Member *parse_type_member(RzBuffer *buf) { rz_return_val_if_fail(buf, NULL); Tpi_LF_Member *member = RZ_NEW0(Tpi_LF_Member); if (!member) { @@ -968,13 +946,11 @@ static Tpi_LF_Member *parse_type_member(RzBuffer *buf, ut16 len, ut16 *read_len) return NULL; } parse_codeview_fld_attribute(&member->fldattr, fldattr); - *read_len += sizeof(ut16); if (!rz_buf_read_le32(buf, &member->index)) { RZ_FREE(member); return NULL; } - *read_len += sizeof(ut32); - if (!parse_type_numeric(buf, &member->offset, read_len)) { + if (!parse_type_numeric(buf, &member->offset)) { RZ_FREE(member); return NULL; } @@ -984,12 +960,11 @@ static Tpi_LF_Member *parse_type_member(RzBuffer *buf, ut16 len, ut16 *read_len) RZ_FREE(member); return NULL; } - parse_type_string(buf, &member->name, len, read_len); - skip_padding(buf, len, read_len, false); + parse_type_string(buf, &member->name); return member; } -static Tpi_LF_StaticMember *parse_type_staticmember(RzBuffer *buf, ut16 len, ut16 *read_len) { +static Tpi_LF_StaticMember *parse_type_staticmember(RzBuffer *buf) { rz_return_val_if_fail(buf, NULL); Tpi_LF_StaticMember *member = RZ_NEW0(Tpi_LF_StaticMember); if (!member) { @@ -1001,18 +976,15 @@ static Tpi_LF_StaticMember *parse_type_staticmember(RzBuffer *buf, ut16 len, ut1 return NULL; } parse_codeview_fld_attribute(&member->fldattr, fldattr); - *read_len += sizeof(ut16); if (!rz_buf_read_le32(buf, &member->index)) { RZ_FREE(member); return NULL; } - *read_len += sizeof(ut32); - parse_type_string(buf, &member->name, len, read_len); - skip_padding(buf, len, read_len, false); + parse_type_string(buf, &member->name); return member; } -static Tpi_LF_OneMethod *parse_type_onemethod(RzBuffer *buf, ut16 len, ut16 *read_len) { +static Tpi_LF_OneMethod *parse_type_onemethod(RzBuffer *buf) { rz_return_val_if_fail(buf, NULL); Tpi_LF_OneMethod *onemethod = RZ_NEW0(Tpi_LF_OneMethod); if (!onemethod) { @@ -1024,26 +996,22 @@ static Tpi_LF_OneMethod *parse_type_onemethod(RzBuffer *buf, ut16 len, ut16 *rea return NULL; } parse_codeview_fld_attribute(&onemethod->fldattr, fldattr); - *read_len += sizeof(ut16); if (!rz_buf_read_le32(buf, &onemethod->index)) { RZ_FREE(onemethod); return NULL; } - *read_len += sizeof(ut32); onemethod->offset_in_vtable = 0; - if (onemethod->fldattr.bits.mprop == MTintro || - onemethod->fldattr.bits.mprop == MTpureintro) { + if (onemethod->fldattr.mprop == MTintro || + onemethod->fldattr.mprop == MTpureintro) { if (!rz_buf_read_le32(buf, &onemethod->offset_in_vtable)) { RZ_FREE(onemethod); } - *read_len += sizeof(ut32); } - parse_type_string(buf, &onemethod->name, len, read_len); - skip_padding(buf, len, read_len, false); + parse_type_string(buf, &onemethod->name); return onemethod; } -static Tpi_LF_BClass *parse_type_bclass(RzBuffer *buf, ut16 len, ut16 *read_len) { +static Tpi_LF_BClass *parse_type_bclass(RzBuffer *buf) { rz_return_val_if_fail(buf, NULL); Tpi_LF_BClass *bclass = RZ_NEW0(Tpi_LF_BClass); if (!bclass) { @@ -1055,13 +1023,11 @@ static Tpi_LF_BClass *parse_type_bclass(RzBuffer *buf, ut16 len, ut16 *read_len) return NULL; } parse_codeview_fld_attribute(&bclass->fldattr, fldattr); - *read_len += sizeof(ut16); if (!rz_buf_read_le32(buf, &bclass->index)) { RZ_FREE(bclass); return NULL; } - *read_len += sizeof(ut32); - if (!parse_type_numeric(buf, &bclass->offset, read_len)) { + if (!parse_type_numeric(buf, &bclass->offset)) { RZ_FREE(bclass); return NULL; } @@ -1071,11 +1037,10 @@ static Tpi_LF_BClass *parse_type_bclass(RzBuffer *buf, ut16 len, ut16 *read_len) RZ_FREE(bclass); return NULL; } - skip_padding(buf, len, read_len, false); return bclass; } -static Tpi_LF_VBClass *parse_type_vbclass(RzBuffer *buf, ut16 len, ut16 *read_len) { +static Tpi_LF_VBClass *parse_type_vbclass(RzBuffer *buf) { rz_return_val_if_fail(buf, NULL); Tpi_LF_VBClass *bclass = RZ_NEW0(Tpi_LF_VBClass); if (!bclass) { @@ -1087,185 +1052,117 @@ static Tpi_LF_VBClass *parse_type_vbclass(RzBuffer *buf, ut16 len, ut16 *read_le return NULL; } parse_codeview_fld_attribute(&bclass->fldattr, fldattr); - *read_len += sizeof(ut16); if (!rz_buf_read_le32(buf, &bclass->direct_vbclass_idx)) { RZ_FREE(bclass); return NULL; } - *read_len += sizeof(ut32); if (!rz_buf_read_le32(buf, &bclass->vb_pointer_idx)) { RZ_FREE(bclass); return NULL; } - *read_len += sizeof(ut32); - parse_type_numeric(buf, &bclass->vb_pointer_offset, read_len); + parse_type_numeric(buf, &bclass->vb_pointer_offset); if (!bclass->vb_pointer_offset.is_integer) { RZ_LOG_ERROR("Integer expected!\n"); free_snumeric(&bclass->vb_pointer_offset); RZ_FREE(bclass); return NULL; } - parse_type_numeric(buf, &bclass->vb_offset_from_vbtable, read_len); + parse_type_numeric(buf, &bclass->vb_offset_from_vbtable); if (!bclass->vb_offset_from_vbtable.is_integer) { RZ_LOG_ERROR("Integer expected!\n"); free_snumeric(&bclass->vb_offset_from_vbtable); RZ_FREE(bclass); return NULL; } - skip_padding(buf, len, read_len, false); return bclass; } -static Tpi_LF_FieldList *parse_type_fieldlist(RzBuffer *buf, ut16 len) { - rz_return_val_if_fail(buf, NULL); +static Tpi_LF_FieldList *parse_type_fieldlist(RzBuffer *b) { + rz_return_val_if_fail(b, NULL); Tpi_LF_FieldList *fieldlist = RZ_NEW0(Tpi_LF_FieldList); if (!fieldlist) { return NULL; } - fieldlist->substructs = rz_list_newf((RzListFree)free_tpi_type); + fieldlist->substructs = rz_pvector_new(free_tpi_type); if (!fieldlist->substructs) { goto error; } - - ut16 read_len = sizeof(ut16); - while (read_len < len) { - RzPdbTpiType *type = RZ_NEW0(RzPdbTpiType); - if (!type) { - rz_list_free(fieldlist->substructs); - goto error; - } - type->length = 0; - type->type_index = 0; - if (!rz_buf_read_le16(buf, &type->leaf_type)) { - RZ_FREE(type); - rz_list_free(fieldlist->substructs); - goto error; - } - read_len += sizeof(ut16); - switch (type->leaf_type) { - case LF_ENUMERATE: - type->type_data = parse_type_enumerate(buf, len, &read_len); - break; - case LF_NESTTYPE: - type->type_data = parse_type_nesttype(buf, len, &read_len); - break; - case LF_VFUNCTAB: - type->type_data = parse_type_vfunctab(buf, len, &read_len); - break; - case LF_METHOD: - type->type_data = parse_type_method(buf, len, &read_len); - break; - case LF_MEMBER: - type->type_data = parse_type_member(buf, len, &read_len); - break; - case LF_ONEMETHOD: - type->type_data = parse_type_onemethod(buf, len, &read_len); - break; - case LF_BCLASS: - type->type_data = parse_type_bclass(buf, len, &read_len); - break; - case LF_VBCLASS: - case LF_IVBCLASS: - type->type_data = parse_type_vbclass(buf, len, &read_len); - break; - case LF_STMEMBER: - type->type_data = parse_type_staticmember(buf, len, &read_len); - break; - case LF_INDEX: - type->type_data = parse_type_index(buf, len, &read_len); - break; - default: - RZ_LOG_ERROR("%s: Unsupported leaf type 0x%" PFMT32x "\n", __FUNCTION__, - type->leaf_type); - RZ_FREE(type); - rz_list_free(fieldlist->substructs); - goto error; - } - if (!type->type_data) { - RZ_FREE(type); - rz_list_free(fieldlist->substructs); - goto error; + while (!buf_empty(b)) { + RzPdbTpiType *t = RzPdbTpiType_from_buf(b, 0, 0); + if (!t) { + continue; } - rz_list_append(fieldlist->substructs, type); + buf_read_padding(b); + rz_pvector_push(fieldlist->substructs, t); } return fieldlist; error: + RZ_LOG_ERROR("failed type_fieldlist\n"); + rz_pvector_free(fieldlist->substructs); RZ_FREE(fieldlist); return NULL; } -static Tpi_LF_Enum *parse_type_enum(RzBuffer *buf, ut16 len) { +static Tpi_LF_Enum *parse_type_enum(RzBuffer *buf) { rz_return_val_if_fail(buf, NULL); Tpi_LF_Enum *_enum = RZ_NEW0(Tpi_LF_Enum); if (!_enum) { return NULL; } - ut16 read_bytes = sizeof(ut16); // include leaf_type if (!rz_buf_read_le16(buf, &_enum->count)) { RZ_FREE(_enum); return NULL; } - read_bytes += sizeof(ut16); ut16 prop; if (!rz_buf_read_le16(buf, &prop)) { RZ_FREE(_enum); return NULL; } parse_codeview_property(&_enum->prop, prop); - read_bytes += sizeof(ut16); if (!rz_buf_read_le32(buf, &_enum->utype)) { RZ_FREE(_enum); return NULL; } - read_bytes += sizeof(ut32); if (!rz_buf_read_le32(buf, &_enum->field_list)) { RZ_FREE(_enum); return NULL; } - read_bytes += sizeof(ut32); - parse_type_string(buf, &_enum->name, len, &read_bytes); - if (has_non_padding(buf, len, &read_bytes)) { - parse_type_string(buf, &_enum->mangled_name, len, &read_bytes); + parse_type_string(buf, &_enum->name); + if (_enum->prop.has_uniquename) { + parse_type_string(buf, &_enum->mangled_name); } - skip_padding(buf, len, &read_bytes, true); return _enum; } -static Tpi_LF_Structure *parse_type_struct(RzBuffer *buf, ut16 len) { +static Tpi_LF_Structure *parse_type_struct(RzBuffer *buf) { rz_return_val_if_fail(buf, NULL); Tpi_LF_Structure *structure = RZ_NEW0(Tpi_LF_Structure); if (!structure) { return NULL; } - ut16 read_bytes = sizeof(ut16); if (!rz_buf_read_le16(buf, &structure->count)) { RZ_FREE(structure); return NULL; } - read_bytes += sizeof(ut16); ut16 prop; if (!rz_buf_read_le16(buf, &prop)) { RZ_FREE(structure); return NULL; } parse_codeview_property(&structure->prop, prop); - read_bytes += sizeof(ut16); if (!rz_buf_read_le32(buf, &structure->field_list)) { RZ_FREE(structure); return NULL; } - read_bytes += sizeof(ut32); if (!rz_buf_read_le32(buf, &structure->derived)) { RZ_FREE(structure); return NULL; } - read_bytes += sizeof(ut32); if (!rz_buf_read_le32(buf, &structure->vshape)) { RZ_FREE(structure); return NULL; } - read_bytes += sizeof(ut32); - if (!parse_type_numeric(buf, &structure->size, &read_bytes)) { + if (!parse_type_numeric(buf, &structure->size)) { RZ_FREE(structure); return NULL; } @@ -1275,53 +1172,44 @@ static Tpi_LF_Structure *parse_type_struct(RzBuffer *buf, ut16 len) { RZ_FREE(structure); return NULL; } - parse_type_string(buf, &structure->name, len, &read_bytes); - if (has_non_padding(buf, len, &read_bytes)) { - parse_type_string(buf, &structure->mangled_name, len, &read_bytes); - } - skip_padding(buf, len, &read_bytes, true); + parse_type_string(buf, &structure->name); + parse_type_string(buf, &structure->mangled_name); return structure; } -static Tpi_LF_Structure_19 *parse_type_struct_19(RzBuffer *buf, ut16 len) { +static Tpi_LF_Structure_19 *parse_type_struct_19(RzBuffer *buf) { rz_return_val_if_fail(buf, NULL); Tpi_LF_Structure_19 *structure = RZ_NEW0(Tpi_LF_Structure_19); if (!structure) { return NULL; } - ut16 read_bytes = sizeof(ut16); ut16 prop; if (!rz_buf_read_le16(buf, &prop)) { RZ_FREE(structure); return NULL; } parse_codeview_property(&structure->prop, prop); - read_bytes += sizeof(ut16); if (!rz_buf_read_le16(buf, &structure->unknown)) { RZ_FREE(structure); return NULL; } - read_bytes += sizeof(ut16); if (!rz_buf_read_le32(buf, &structure->field_list)) { RZ_FREE(structure); return NULL; } - read_bytes += sizeof(ut32); if (!rz_buf_read_le32(buf, &structure->derived)) { RZ_FREE(structure); return NULL; } - read_bytes += sizeof(ut32); if (!rz_buf_read_le32(buf, &structure->vshape)) { RZ_FREE(structure); return NULL; } - read_bytes += sizeof(ut32); - if (!parse_type_numeric(buf, &structure->unknown1, &read_bytes)) { + if (!parse_type_numeric(buf, &structure->unknown1)) { RZ_FREE(structure); return NULL; } - if (!parse_type_numeric(buf, &structure->size, &read_bytes)) { + if (!parse_type_numeric(buf, &structure->size)) { RZ_FREE(structure); return NULL; } @@ -1331,123 +1219,107 @@ static Tpi_LF_Structure_19 *parse_type_struct_19(RzBuffer *buf, ut16 len) { RZ_FREE(structure); return NULL; } - parse_type_string(buf, &structure->name, len, &read_bytes); - if (has_non_padding(buf, len, &read_bytes)) { - parse_type_string(buf, &structure->mangled_name, len, &read_bytes); - } - skip_padding(buf, len, &read_bytes, true); + parse_type_string(buf, &structure->name); + parse_type_string(buf, &structure->mangled_name); return structure; } -static Tpi_LF_Pointer *parse_type_pointer(RzBuffer *buf, ut16 len) { +static Tpi_LF_Pointer *parse_type_pointer(RzBuffer *buf) { rz_return_val_if_fail(buf, NULL); Tpi_LF_Pointer *pointer = RZ_NEW0(Tpi_LF_Pointer); if (!pointer) { return NULL; } - ut16 read_bytes = sizeof(ut16); if (!rz_buf_read_le32(buf, &pointer->utype)) { RZ_FREE(pointer); return NULL; } - read_bytes += sizeof(ut32); ut32 ptrattr; if (!rz_buf_read_le32(buf, &ptrattr)) { RZ_FREE(pointer); return NULL; } parse_codeview_pointer_attribute(&pointer->ptr_attr, ptrattr); - read_bytes += sizeof(ut32); - if (pointer->ptr_attr.bits.ptrmode == PTR_MODE_PMFUNC || - pointer->ptr_attr.bits.ptrmode == PTR_MODE_PMEM) { - read_bytes += sizeof(ut32); + if (pointer->ptr_attr.ptrmode == PTR_MODE_PMFUNC || + pointer->ptr_attr.ptrmode == PTR_MODE_PMEM) { if (!rz_buf_read_le32(buf, &pointer->pmember.pmclass)) { RZ_FREE(pointer); return NULL; } - read_bytes += sizeof(ut16); if (!rz_buf_read_le16(buf, &pointer->pmember.pmtype)) { RZ_FREE(pointer); return NULL; } - } else if (pointer->ptr_attr.bits.ptrtype == PTR_BASE_TYPE) { - read_bytes += sizeof(ut32); + } else if (pointer->ptr_attr.ptrtype == PTR_BASE_TYPE) { if (!rz_buf_read_le32(buf, &pointer->pbase.index)) { RZ_FREE(pointer); return NULL; } } - skip_padding(buf, len, &read_bytes, true); return pointer; } -static Tpi_LF_Array *parse_type_array(RzBuffer *buf, ut16 len) { +static Tpi_LF_Array *parse_type_array(RzBuffer *buf, TpiLeafType leaf) { rz_return_val_if_fail(buf, NULL); Tpi_LF_Array *array = RZ_NEW0(Tpi_LF_Array); if (!array) { return NULL; } - ut16 read_bytes = sizeof(ut16); if (!rz_buf_read_le32(buf, &array->element_type)) { - RZ_FREE(array); - return NULL; + goto err; } - read_bytes += sizeof(ut32); if (!rz_buf_read_le32(buf, &array->index_type)) { - RZ_FREE(array); - return NULL; + goto err; } - read_bytes += sizeof(ut32); - if (!parse_type_numeric(buf, &array->size, &read_bytes)) { - RZ_FREE(array); - return NULL; + if (leaf == LF_STRIDED_ARRAY) { + if (!rz_buf_read_le32(buf, &array->stride)) { + goto err; + } + } + if (!parse_type_numeric(buf, &array->size)) { + goto err; } if (!array->size.is_integer) { RZ_LOG_ERROR("Integer expected!\n"); free_snumeric(&array->size); - RZ_FREE(array); - return NULL; + goto err; } - parse_type_string(buf, &array->name, len, &read_bytes); - skip_padding(buf, len, &read_bytes, true); + parse_type_string(buf, &array->name); return array; +err: + RZ_FREE(array); + return NULL; } -static Tpi_LF_Modifier *parse_type_modifier(RzBuffer *buf, ut16 len) { +static Tpi_LF_Modifier *parse_type_modifier(RzBuffer *buf) { rz_return_val_if_fail(buf, NULL); Tpi_LF_Modifier *modifier = RZ_NEW0(Tpi_LF_Modifier); if (!modifier) { return NULL; } - ut16 read_bytes = sizeof(ut16); if (!rz_buf_read_le32(buf, &modifier->modified_type)) { RZ_FREE(modifier); return NULL; } - read_bytes += sizeof(ut32); ut16 umodifier; if (!rz_buf_read_le16(buf, &umodifier)) { RZ_FREE(modifier); return NULL; } parse_codeview_modifier(&modifier->umodifier, umodifier); - read_bytes += sizeof(ut16); - skip_padding(buf, len, &read_bytes, true); return modifier; } -static Tpi_LF_Arglist *parse_type_arglist(RzBuffer *buf, ut16 len) { +static Tpi_LF_Arglist *parse_type_arglist(RzBuffer *buf) { rz_return_val_if_fail(buf, NULL); Tpi_LF_Arglist *arglist = RZ_NEW0(Tpi_LF_Arglist); if (!arglist) { return NULL; } - ut16 read_bytes = sizeof(ut16); if (!rz_buf_read_le32(buf, &arglist->count)) { RZ_FREE(arglist); return NULL; } - read_bytes += sizeof(ut32); arglist->arg_type = (ut32 *)malloc(sizeof(ut32) * arglist->count); if (!arglist->arg_type) { RZ_LOG_ERROR("Error allocating memory.\n"); @@ -1460,67 +1332,54 @@ static Tpi_LF_Arglist *parse_type_arglist(RzBuffer *buf, ut16 len) { RZ_FREE(arglist); return NULL; } - read_bytes += sizeof(ut32); } - skip_padding(buf, len, &read_bytes, true); - return arglist; } -static Tpi_LF_MFcuntion *parse_type_mfunction(RzBuffer *buf, ut16 len) { +static Tpi_LF_MFcuntion *parse_type_mfunction(RzBuffer *buf) { rz_return_val_if_fail(buf, NULL); Tpi_LF_MFcuntion *mfunc = RZ_NEW0(Tpi_LF_MFcuntion); if (!mfunc) { return NULL; } - ut16 read_bytes = sizeof(ut16); if (!rz_buf_read_le32(buf, &mfunc->return_type)) { RZ_FREE(mfunc); return NULL; } - read_bytes += sizeof(ut32); if (!rz_buf_read_le32(buf, &mfunc->class_type)) { RZ_FREE(mfunc); return NULL; } - read_bytes += sizeof(ut32); if (!rz_buf_read_le32(buf, &mfunc->this_type)) { RZ_FREE(mfunc); return NULL; } - read_bytes += sizeof(ut32); if (!rz_buf_read8(buf, (ut8 *)&mfunc->call_conv)) { RZ_FREE(mfunc); return NULL; } - read_bytes += sizeof(ut8); ut8 funcattr; if (!rz_buf_read8(buf, &funcattr)) { RZ_FREE(mfunc); return NULL; } parse_codeview_func_attribute(&mfunc->func_attr, funcattr); - read_bytes += sizeof(ut8); if (!rz_buf_read_le16(buf, &mfunc->parm_count)) { RZ_FREE(mfunc); return NULL; } - read_bytes += sizeof(ut16); if (!rz_buf_read_le32(buf, &mfunc->arglist)) { RZ_FREE(mfunc); return NULL; } - read_bytes += sizeof(ut32); if (!rz_buf_read_le32(buf, (ut32 *)&mfunc->this_adjust)) { RZ_FREE(mfunc); return NULL; } - read_bytes += sizeof(ut32); - skip_padding(buf, len, &read_bytes, true); return mfunc; } -static Tpi_LF_MethodList *parse_type_methodlist(RzBuffer *buf, ut16 len) { +static Tpi_LF_MethodList *parse_type_methodlist(RzBuffer *buf) { rz_return_val_if_fail(buf, NULL); Tpi_LF_MethodList *mlist = RZ_NEW0(Tpi_LF_MethodList); if (!mlist) { @@ -1531,8 +1390,7 @@ static Tpi_LF_MethodList *parse_type_methodlist(RzBuffer *buf, ut16 len) { RZ_LOG_ERROR("Error allocating memory.\n"); goto error; } - ut16 read_bytes = sizeof(ut16); - while (read_bytes < len) { + while (!buf_empty(buf)) { Tpi_Type_MethodListMember *member = RZ_NEW0(Tpi_Type_MethodListMember); if (!member) { continue; @@ -1545,35 +1403,30 @@ static Tpi_LF_MethodList *parse_type_methodlist(RzBuffer *buf, ut16 len) { return NULL; } parse_codeview_fld_attribute(&member->fldattr, fldattr); - read_bytes += sizeof(ut16); if (!rz_buf_read_le16(buf, &member->pad)) { RZ_FREE(member); rz_list_free(mlist->members); RZ_FREE(mlist); return NULL; } - read_bytes += sizeof(ut16); if (!rz_buf_read_le32(buf, &member->type)) { RZ_FREE(member); rz_list_free(mlist->members); RZ_FREE(mlist); return NULL; } - read_bytes += sizeof(ut32); member->optional_offset = 0; - if (member->fldattr.bits.mprop == MTintro || - member->fldattr.bits.mprop == MTpureintro) { + if (member->fldattr.mprop == MTintro || + member->fldattr.mprop == MTpureintro) { if (!rz_buf_read_le32(buf, &member->optional_offset)) { RZ_FREE(member); rz_list_free(mlist->members); RZ_FREE(mlist); return NULL; } - read_bytes += sizeof(ut32); } rz_list_append(mlist->members, member); } - skip_padding(buf, len, &read_bytes, true); return mlist; error: @@ -1581,69 +1434,58 @@ static Tpi_LF_MethodList *parse_type_methodlist(RzBuffer *buf, ut16 len) { return NULL; } -static Tpi_LF_Procedure *parse_type_procedure(RzBuffer *buf, ut16 len) { +static Tpi_LF_Procedure *parse_type_procedure(RzBuffer *buf) { rz_return_val_if_fail(buf, NULL); Tpi_LF_Procedure *proc = RZ_NEW0(Tpi_LF_Procedure); if (!proc) { return NULL; } - ut16 read_bytes = sizeof(ut16); if (!rz_buf_read_le32(buf, &proc->return_type)) { RZ_FREE(proc); return NULL; } - read_bytes += sizeof(ut32); if (!rz_buf_read8(buf, (ut8 *)&proc->call_conv)) { RZ_FREE(proc); return NULL; } - read_bytes += sizeof(ut8); ut8 funcattr; if (!rz_buf_read8(buf, &funcattr)) { RZ_FREE(proc); return NULL; } parse_codeview_func_attribute(&proc->func_attr, funcattr); - read_bytes += sizeof(ut8); if (!rz_buf_read_le16(buf, &proc->parm_count)) { RZ_FREE(proc); return NULL; } - read_bytes += sizeof(ut16); if (!rz_buf_read_le32(buf, &proc->arg_list)) { RZ_FREE(proc); return NULL; } - read_bytes += sizeof(ut32); - skip_padding(buf, len, &read_bytes, true); return proc; } -static Tpi_LF_Union *parse_type_union(RzBuffer *buf, ut16 len) { +static Tpi_LF_Union *parse_type_union(RzBuffer *buf) { rz_return_val_if_fail(buf, NULL); Tpi_LF_Union *unin = RZ_NEW0(Tpi_LF_Union); if (!unin) { return NULL; } - ut16 read_bytes = sizeof(ut16); if (!rz_buf_read_le16(buf, &unin->count)) { RZ_FREE(unin); return NULL; } - read_bytes += sizeof(ut16); ut16 prop; if (!rz_buf_read_le16(buf, &prop)) { RZ_FREE(unin); return NULL; } parse_codeview_property(&unin->prop, prop); - read_bytes += sizeof(ut16); if (!rz_buf_read_le32(buf, &unin->field_list)) { RZ_FREE(unin); return NULL; } - read_bytes += sizeof(ut32); - if (!parse_type_numeric(buf, &unin->size, &read_bytes)) { + if (!parse_type_numeric(buf, &unin->size)) { RZ_FREE(unin); } if (!unin->size.is_integer) { @@ -1652,53 +1494,42 @@ static Tpi_LF_Union *parse_type_union(RzBuffer *buf, ut16 len) { RZ_FREE(unin); return NULL; } - parse_type_string(buf, &unin->name, len, &read_bytes); - if (has_non_padding(buf, len, &read_bytes)) { - parse_type_string(buf, &unin->mangled_name, len, &read_bytes); - } - - skip_padding(buf, len, &read_bytes, true); + parse_type_string(buf, &unin->name); + parse_type_string(buf, &unin->mangled_name); return unin; } -static Tpi_LF_Bitfield *parse_type_bitfield(RzBuffer *buf, ut16 len) { +static Tpi_LF_Bitfield *parse_type_bitfield(RzBuffer *buf) { rz_return_val_if_fail(buf, NULL); Tpi_LF_Bitfield *bf = RZ_NEW0(Tpi_LF_Bitfield); if (!bf) { return NULL; } - ut16 read_bytes = sizeof(ut16); if (!rz_buf_read_le32(buf, &bf->base_type)) { RZ_FREE(bf); return NULL; } - read_bytes += sizeof(ut32); if (!rz_buf_read8(buf, &bf->length)) { RZ_FREE(bf); return NULL; } - read_bytes += sizeof(ut8); if (!rz_buf_read8(buf, &bf->position)) { RZ_FREE(bf); return NULL; } - read_bytes += sizeof(ut8); - skip_padding(buf, len, &read_bytes, true); return bf; } -static Tpi_LF_Vtshape *parse_type_vtshape(RzBuffer *buf, ut16 len) { +static Tpi_LF_Vtshape *parse_type_vtshape(RzBuffer *buf) { rz_return_val_if_fail(buf, NULL); Tpi_LF_Vtshape *vt = RZ_NEW0(Tpi_LF_Vtshape); if (!vt) { return NULL; } - ut16 read_bytes = sizeof(ut16); if (!rz_buf_read_le16(buf, &vt->count)) { RZ_FREE(vt); return NULL; } - read_bytes += sizeof(ut16); ut16 size = (4 * vt->count + (vt->count % 2) * 4) / 8; vt->vt_descriptors = (char *)malloc(size); if (!vt->vt_descriptors) { @@ -1707,75 +1538,179 @@ static Tpi_LF_Vtshape *parse_type_vtshape(RzBuffer *buf, ut16 len) { return NULL; } rz_buf_read(buf, (ut8 *)vt->vt_descriptors, size); - read_bytes += size; - skip_padding(buf, len, &read_bytes, true); return vt; } -static bool parse_tpi_types(RzBuffer *buf, RzPdbTpiType *type) { - if (!buf || !type) { - return false; +static Tpi_LF_Vftable *vftable_parse(RzBuffer *buf) { + rz_return_val_if_fail(buf, NULL); + Tpi_LF_Vftable *vft = RZ_NEW0(Tpi_LF_Vftable); + if (!vft) { + return NULL; } - if (!rz_buf_read_le16(buf, &type->length)) { - return false; + + if (!rz_buf_read_le32(buf, (ut32 *)&vft->complete_class)) { + goto err; } - if (!rz_buf_read_le16(buf, &type->leaf_type)) { - return false; + if (!rz_buf_read_le32(buf, (ut32 *)&vft->override_vftable)) { + goto err; + } + if (!rz_buf_read_le32(buf, (ut32 *)&vft->vfptr_offset)) { + goto err; + } + ut32 names_len = 0; + if (!rz_buf_read_le32(buf, &names_len)) { + goto err; + } + rz_pvector_init(&vft->method_names, free); + + while (rz_buf_peek(buf) < LF_PAD0) { + char *name = NULL; + ut64 nlen = rz_buf_read_string(buf, &name); + if (nlen <= 0) { + continue; + } + rz_pvector_push(&vft->method_names, name); + } + return vft; +err: + rz_pvector_fini(&vft->method_names); + RZ_FREE(vft); + return NULL; +} + +static Tpi_LF_Label *labal_parse(RzBuffer *buf) { + rz_return_val_if_fail(buf, NULL); + Tpi_LF_Label *record = RZ_NEW0(Tpi_LF_Label); + if (!record) { + return NULL; + } + + if (!rz_buf_read_le32(buf, (ut32 *)&record->mode)) { + goto err; + } + return record; +err: + RZ_FREE(record); + return NULL; +} + +static RzPdbTpiType *RzPdbTpiType_from_buf(RzBuffer *b, ut32 index, ut16 length) { + if (!b) { + return NULL; + } + ut16 leaf = 0; + if (!rz_buf_read_le16(b, &leaf)) { + return NULL; } - switch (type->leaf_type) { + + void *data = NULL; + switch (leaf) { case LF_FIELDLIST: - type->type_data = parse_type_fieldlist(buf, type->length); + data = parse_type_fieldlist(b); break; case LF_ENUM: - type->type_data = parse_type_enum(buf, type->length); + data = parse_type_enum(b); break; case LF_CLASS: case LF_STRUCTURE: - type->type_data = parse_type_struct(buf, type->length); + data = parse_type_struct(b); break; case LF_CLASS_19: case LF_STRUCTURE_19: - type->type_data = parse_type_struct_19(buf, type->length); + data = parse_type_struct_19(b); break; case LF_POINTER: - type->type_data = parse_type_pointer(buf, type->length); + data = parse_type_pointer(b); break; case LF_ARRAY: - type->type_data = parse_type_array(buf, type->length); + case LF_ARRAY_ST: + case LF_STRIDED_ARRAY: + data = parse_type_array(b, leaf); break; case LF_MODIFIER: - type->type_data = parse_type_modifier(buf, type->length); + data = parse_type_modifier(b); break; case LF_ARGLIST: - type->type_data = parse_type_arglist(buf, type->length); + data = parse_type_arglist(b); break; case LF_MFUNCTION: - type->type_data = parse_type_mfunction(buf, type->length); + data = parse_type_mfunction(b); break; case LF_METHODLIST: - type->type_data = parse_type_methodlist(buf, type->length); + data = parse_type_methodlist(b); break; case LF_PROCEDURE: - type->type_data = parse_type_procedure(buf, type->length); + data = parse_type_procedure(b); break; case LF_UNION: - type->type_data = parse_type_union(buf, type->length); + data = parse_type_union(b); break; case LF_BITFIELD: - type->type_data = parse_type_bitfield(buf, type->length); + data = parse_type_bitfield(b); break; case LF_VTSHAPE: - type->type_data = parse_type_vtshape(buf, type->length); + data = parse_type_vtshape(b); + break; + case LF_VFTABLE: + data = vftable_parse(b); + break; + case LF_LABEL: + data = labal_parse(b); + break; + case LF_ENUMERATE: + data = parse_type_enumerate(b); + break; + case LF_NESTTYPE: + data = parse_type_nesttype(b); + break; + case LF_VFUNCTAB: + data = parse_type_vfunctab(b); + break; + case LF_METHOD: + data = parse_type_method(b); + break; + case LF_MEMBER: + data = parse_type_member(b); + break; + case LF_ONEMETHOD: + data = parse_type_onemethod(b); + break; + case LF_BCLASS: + data = parse_type_bclass(b); + break; + case LF_VBCLASS: + case LF_IVBCLASS: + data = parse_type_vbclass(b); + break; + case LF_STMEMBER: + data = parse_type_staticmember(b); + break; + case LF_INDEX: + data = parse_type_index(b); break; default: - RZ_LOG_ERROR("%s: unsupported leaf type: 0x%" PFMT32x "\n", __FUNCTION__, type->leaf_type); - return false; + RZ_LOG_DEBUG("%s: 0x%" PFMT32x ": unsupported leaf type: 0x%" PFMT32x "\n", __FUNCTION__, index, leaf); + break; } - return true; + + if (!data && !length && !index) { + return NULL; + } + + RzPdbTpiType *type = RZ_NEW0(RzPdbTpiType); + if (!type) { + free(data); + return NULL; + } + type->index = index; + type->length = length; + type->leaf = leaf; + type->data = data; + return type; } static bool parse_tpi_stream_header(RzPdbTpiStream *s, RzBuffer *buf) { - return rz_buf_read_le32(buf, &s->header.Version) && + return rz_buf_read_le32(buf, (ut32 *)&s->header.Version) && rz_buf_read_le32(buf, &s->header.HeaderSize) && rz_buf_read_le32(buf, &s->header.TypeIndexBegin) && rz_buf_read_le32(buf, &s->header.TypeIndexEnd) && @@ -1811,27 +1746,35 @@ RZ_IPI bool parse_tpi_stream(RzPdb *pdb, RzPdbMsfStream *stream) { return false; } s->types = NULL; - RzBuffer *buf = stream->stream_data; - if (!parse_tpi_stream_header(s, buf)) { + RzBuffer *steam_buffer = stream->stream_data; + if (!parse_tpi_stream_header(s, steam_buffer)) { return false; } if (s->header.HeaderSize != sizeof(RzPdbTpiStreamHeader)) { RZ_LOG_ERROR("Corrupted TPI stream.\n"); return false; } - RzPdbTpiType *type; - for (ut32 i = s->header.TypeIndexBegin; i < s->header.TypeIndexEnd; i++) { - type = RZ_NEW0(RzPdbTpiType); - if (!type) { - continue; + for (ut32 index = s->header.TypeIndexBegin; index < s->header.TypeIndexEnd; index++) { + ut16 length = 0; + if (!rz_buf_read_le16(steam_buffer, &length)) { + return false; } - type->type_index = i; - if (!parse_tpi_types(buf, type) || !type->type_data) { - RZ_LOG_ERROR("Parse TPI type error. idx in stream: 0x%" PFMT32x "\n", i); - RZ_FREE(type); + RzBuffer *b = buf_take(steam_buffer, length); + if (!b) { return false; } - rz_rbtree_insert(&s->types, &type->type_index, &type->rb, tpi_type_node_cmp, NULL); + + RzPdbTpiType *type = RzPdbTpiType_from_buf(b, index, length); + if (!type) { + goto err; + } + rz_buf_free(b); + rz_rbtree_insert(&s->types, &type->index, &type->rb, tpi_type_node_cmp, NULL); + continue; + err: + rz_buf_free(b); + free(type); + return false; } return true; } @@ -1841,7 +1784,8 @@ RZ_IPI bool parse_tpi_stream(RzPdb *pdb, RzPdbMsfStream *stream) { * \param stream TPI Stream * \param index TPI Stream Index */ -RZ_API RZ_BORROW RzPdbTpiType *rz_bin_pdb_get_type_by_index(RZ_NONNULL RzPdbTpiStream *stream, ut32 index) { +RZ_API RZ_BORROW RzPdbTpiType *rz_bin_pdb_get_type_by_index( + RZ_NONNULL RzPdbTpiStream *stream, ut32 index) { rz_return_val_if_fail(stream, NULL); if (index == 0) { return NULL; @@ -1849,11 +1793,10 @@ RZ_API RZ_BORROW RzPdbTpiType *rz_bin_pdb_get_type_by_index(RZ_NONNULL RzPdbTpiS RBNode *node = rz_rbtree_find(stream->types, &index, tpi_type_node_cmp, NULL); if (!node) { - if (!is_simple_type(stream, index)) { - return NULL; - } else { + if (is_simple_type(stream, index)) { return parse_simple_type(stream, index); } + return NULL; } RzPdbTpiType *type = container_of(node, RzPdbTpiType, rb); return type; diff --git a/librz/bin/pdb/tpi.h b/librz/bin/pdb/tpi.h index 327a3a6361b..4027fc5f07f 100644 --- a/librz/bin/pdb/tpi.h +++ b/librz/bin/pdb/tpi.h @@ -6,6 +6,40 @@ #include +/// enumeration for virtual shape table entries +typedef enum { + VTS_near = 0x00, + VTS_far = 0x01, + VTS_thin = 0x02, + VTS_outer = 0x03, + VTS_meta = 0x04, + VTS_near32 = 0x05, + VTS_far32 = 0x06, + VTS_unused = 0x07 +} TpiCV_VTS_desc; + +/// enumeration for LF_LABEL address modes +typedef enum { + LABEL_NEAR = 0, // near return + LABEL_FAR = 4 // far return +} TpiCV_LABEL_TYPE; + +/// enumeration for HFA kinds +typedef enum { + CV_HFA_none = 0, + CV_HFA_float = 1, + CV_HFA_double = 2, + CV_HFA_other = 3 +} TpiCV_HFA; + +/// enumeration for MoCOM UDT kinds +typedef enum CV_MOCOM_UDT_e { + CV_MOCOM_UDT_none = 0, + CV_MOCOM_UDT_ref = 1, + CV_MOCOM_UDT_value = 2, + CV_MOCOM_UDT_interface = 3 +} TpiCV_MOCOM_UDT; + typedef enum { DIRECT = 0, // Not a pointer NEAR_POINTER = 1, // Near pointer @@ -95,6 +129,7 @@ typedef enum { LF_ENDPRECOMP = 0x0014, // type record describing end of precompiled types that can be LF_OEM_16t = 0x0015, // type record for OEM definable type strings LF_TYPESERVER_ST = 0x0016, // type record describing using of a type server + LF_SKIP_16t = 0x0200, LF_ARGLIST_16t = 0x0201, LF_DEFARG_16t = 0x0202, @@ -108,6 +143,7 @@ typedef enum { LF_DIMVARU_16t = 0x020A, // type record for dimensioned array with variable bounds LF_DIMVARLU_16t = 0x020B, // type record for dimensioned array with variable bounds LF_REFSYM = 0x020C, // type record for referenced symbol + LF_BCLASS_16t = 0x0400, // subfield record for base class field LF_VBCLASS_16t = 0x0401, // subfield record for direct and indirect virtual base class field LF_IVBCLASS_16t = 0x0402, @@ -122,6 +158,7 @@ typedef enum { LF_FRIENDCLS_16t = 0x040B, // subfield record for friend class LF_ONEMETHOD_16t = 0x040C, // subfield record for nonoverloaded method LF_VFUNCOFF_16t = 0x040D, // subfield record for virtual function table pointer with offset + LF_TI16_MAX = 0x1000, LF_MODIFIER = 0x1001, // type record for a generalized built-in type modifier LF_POINTER = 0x1002, @@ -140,6 +177,7 @@ typedef enum { LF_OEM = 0x100F, // type record for OEM definable type strings LF_ALIAS_ST = 0x1010, LF_OEM2 = 0x1011, // type record for OEM definable type strings + LF_SKIP = 0x1200, LF_ARGLIST = 0x1201, LF_DEFARG_ST = 0x1202, @@ -151,6 +189,7 @@ typedef enum { LF_DIMCONLU = 0x1208, // type record for dimensioned array with constant bounds LF_DIMVARU = 0x1209, // type record for dimensioned array with variable bounds LF_DIMVARLU = 0x120A, // type record for dimensioned array with variable bounds + LF_BCLASS = 0x1400, // subfield record for base class field LF_VBCLASS = 0x1401, // subfield record for direct and indirect virtual base class field LF_IVBCLASS = 0x1402, @@ -167,6 +206,7 @@ typedef enum { LF_NESTTYPEEX_ST = 0x140D, // type record for nested (scoped) type definition, with attributes LF_MEMBERMODIFY_ST = 0x140E, // type record for modifications to members LF_MANAGED_ST = 0x140F, + LF_ST_MAX = 0x1500, LF_TYPESERVER = 0x1501, // type record describing using of a type server LF_ENUMERATE = 0x1502, // subfield record for enumerate @@ -189,6 +229,18 @@ typedef enum { LF_MEMBERMODIFY = 0x1513, // type record for modifications to members LF_MANAGED = 0x1514, LF_TYPESERVER2 = 0x1515, // type record describing using of a type server with v7 (GUID) signatures + LF_STRIDED_ARRAY = 0x1516, // same as LF_ARRAY, but with stride between adjacent elements + LF_HLSL = 0x1517, + LF_MODIFIER_EX = 0x1518, + LF_INTERFACE = 0x1519, + LF_BINTERFACE = 0x151a, + LF_VECTOR = 0x151b, + LF_MATRIX = 0x151c, + LF_VFTABLE = 0x151d, // a virtual function table + LF_ENDOFLEAFRECORD = LF_VFTABLE, + LF_TYPE_LAST, // one greater than the last type record + LF_TYPE_MAX = LF_TYPE_LAST - 1, + LF_FUNCTION_ID = 0x1601, LF_MEMBER_FUNCTION_ID = 0x1602, LF_BUILD_INFO = 0x1603, @@ -198,6 +250,8 @@ typedef enum { LF_USER_DEFINED_TYPE_MODULE_SOURCE_AND_LINE = 0x1607, LF_CLASS_19 = 0x1608, LF_STRUCTURE_19 = 0x1609, + LF_ID_LAST, // one greater than the last ID record + LF_ID_MAX = LF_ID_LAST - 1, /** the following are numeric leaves. They are used to indicate the * size of the following variable length data. When the numeric @@ -227,6 +281,8 @@ typedef enum { LF_DECIMAL = 0x8019, LF_DATE = 0x801A, LF_UTF8STRING = 0x801B, + LF_REAL16 = 0x801c, + LF_PAD0 = 0x00F0, LF_PAD1 = 0x00F1, LF_PAD2 = 0x00F2, @@ -247,23 +303,21 @@ typedef enum { LF_MAX = 0xFFFF } TpiLeafType; -typedef union { - struct { - ut16 packed : 1; // true if structure is packed - ut16 ctor : 1; // true if constructors or destructors present - ut16 ovlops : 1; // true if overloaded operators present - ut16 isnested : 1; // true if this is a nested class - ut16 cnested : 1; // true if this class contains nested types - ut16 opassign : 1; // true if overloaded assignment (=) - ut16 opcast : 1; // true if casting methods - ut16 fwdref : 1; // true if forward reference (incomplete defn) - ut16 scoped : 1; // scoped definition - ut16 hasuniquename : 1; // true if there is a decorated name following the regular name - ut16 sealed : 1; // true if class cannot be used as a base class - ut16 hfa : 2; // CV_HFA_e - ut16 intrinsic : 1; // true if class is an intrinsic type (e.g. __m128d) - ut16 mocom : 2; // CV_MOCOM_UDT_e - } bits; +typedef struct { + ut16 packed : 1; // true if structure is packed + ut16 ctor : 1; // true if constructors or destructors present + ut16 ovlops : 1; // true if overloaded operators present + ut16 isnested : 1; // true if this is a nested class + ut16 cnested : 1; // true if this class contains nested types + ut16 opassign : 1; // true if overloaded assignment (=) + ut16 opcast : 1; // true if casting methods + ut16 fwdref : 1; // true if forward reference (incomplete defn) + ut16 scoped : 1; // scoped definition + ut16 has_uniquename : 1; // true if there is a decorated name following the regular name + ut16 sealed : 1; // true if class cannot be used as a base class + ut16 hfa : 2; // CV_HFA_e + ut16 intrinsic : 1; // true if class is an intrinsic type (e.g. __m128d) + ut16 mocom : 2; // CV_MOCOM_UDT_e } TpiCVProperty; typedef enum { @@ -284,26 +338,22 @@ typedef enum { AccessMax } TpiCVAccess; -typedef union { - struct { - ut16 access : 2; // access protection CV_access_t - ut16 mprop : 3; // method properties CV_methodprop_t - ut16 pseudo : 1; // compiler generated fcn and does not exist - ut16 noinherit : 1; // true if class cannot be inherited - ut16 noconstruct : 1; // true if class cannot be constructed - ut16 compgenx : 1; // compiler generated fcn and does exist - ut16 sealed : 1; // true if method cannot be overridden - ut16 unused : 6; // unused - } bits; +typedef struct { + ut16 access : 2; // access protection CV_access_t + ut16 mprop : 3; // method properties CV_methodprop_t + ut16 pseudo : 1; // compiler generated fcn and does not exist + ut16 noinherit : 1; // true if class cannot be inherited + ut16 noconstruct : 1; // true if class cannot be constructed + ut16 compgenx : 1; // compiler generated fcn and does exist + ut16 sealed : 1; // true if method cannot be overridden + ut16 unused : 6; // unused } TpiCVFldattr; -typedef union { - struct cv_funcattr { - unsigned char cxxreturnudt : 1; // true if C++ style ReturnUDT - unsigned char ctor : 1; // true if func is an instance constructor - unsigned char ctorvbase : 1; // true if func is an instance constructor of a class with virtual bases - unsigned char unused : 5; // unused - } bits; +typedef struct cv_funcattr { + unsigned char cxxreturnudt : 1; // true if C++ style ReturnUDT + unsigned char ctor : 1; // true if func is an instance constructor + unsigned char ctorvbase : 1; // true if func is an instance constructor of a class with virtual bases + unsigned char unused : 5; // unused } TpiCVFuncattr; typedef struct { @@ -333,13 +383,11 @@ typedef struct { ut8 pad; } Tpi_LF_Arglist; -typedef union { - struct { - ut16 const_ : 1; - ut16 volatile_ : 1; - ut16 unaligned : 1; - ut16 unused : 13; - } bits; +typedef struct { + ut16 const_ : 1; + ut16 volatile_ : 1; + ut16 unaligned : 1; + ut16 unused : 13; } TpiCVModifier; typedef struct { @@ -355,7 +403,7 @@ typedef enum { PTR_MODE_PMFUNC = 0x00000003, // pointer to member function PTR_MODE_RVREF = 0x00000004, // r-value reference PTR_MODE_RESERVED = 0x00000005, // first unused pointer mode - ModeMax + PTR_MODE_Max } TpiCVPtrMode; typedef enum { @@ -385,24 +433,22 @@ typedef enum { PTR_FAR32 = 0x0000000B, PTR_64 = 0x0000000C, PTR_UNUSEDPTR = 0x0000000D, - TypeMax + PTR_Max } TpiCVType; -typedef union { - struct { - ut32 ptrtype : 5; // ordinal specifying pointer type - ut32 ptrmode : 3; // ordinal specifying pointer mode - ut32 flat32 : 1; // true if 0:32 pointer - ut32 volatile_ : 1; // TRUE if volatile pointer - ut32 const_ : 1; // TRUE if const pointer - ut32 unaligned : 1; // TRUE if unaligned pointer - ut32 restrict_ : 1; // TRUE if restricted pointer (allow agressive opts) - ut32 size : 6; // size of pointer (in bytes) - ut32 mocom : 1; // TRUE if it is a MoCOM pointer (^ or %) - ut32 lref : 1; // TRUE if it is this pointer of member function with & ref-qualifier - ut32 rref : 1; // TRUE if it is this pointer of member function with && ref-qualifier - ut32 unused : 10; // pad out to 32-bits for following cv_typ_t's - } bits; +typedef struct { + ut32 ptrtype : 5; // ordinal specifying pointer type + ut32 ptrmode : 3; // ordinal specifying pointer mode + ut32 flat32 : 1; // true if 0:32 pointer + ut32 volatile_ : 1; // TRUE if volatile pointer + ut32 const_ : 1; // TRUE if const pointer + ut32 unaligned : 1; // TRUE if unaligned pointer + ut32 restrict_ : 1; // TRUE if restricted pointer (allow agressive opts) + ut32 size : 6; // size of pointer (in bytes) + ut32 mocom : 1; // TRUE if it is a MoCOM pointer (^ or %) + ut32 lref : 1; // TRUE if it is this pointer of member function with & ref-qualifier + ut32 rref : 1; // TRUE if it is this pointer of member function with && ref-qualifier + ut32 unused : 10; // pad out to 32-bits for following cv_typ_t's } TpiCVPointerAttr; typedef struct { @@ -434,6 +480,7 @@ typedef struct { typedef struct { ut32 element_type; ut32 index_type; + ut32 stride; Tpi_Type_Numeric size; Tpi_Type_String name; ut8 pad; @@ -487,6 +534,22 @@ typedef struct { ut8 pad; } Tpi_LF_Vtshape; +/// type record for a virtual function table +typedef struct { + ut16 leaf; // LF_VFTABLE + TpiCVType complete_class; // class/structure that owns the vftable + TpiCVType override_vftable; // vftable from which this vftable is derived + ut32 vfptr_offset; // offset of the vfptr to this table, relative to the start of the object layout. + RzPVector /**/ method_names; // array of names. + // The first is the name of the vtable. + // The others are the names of the methods. +} Tpi_LF_Vftable; + +// LF_LABEL +typedef struct { + TpiCV_LABEL_TYPE mode; +} Tpi_LF_Label; + typedef struct { ut16 count; TpiCVProperty prop; @@ -549,9 +612,9 @@ typedef struct { } Tpi_LF_StaticMember; typedef struct { - TpiCVFldattr fldattr; + ut16 leaf; + ut16 pad0; ut32 index; - ut8 pad; } Tpi_LF_Index; typedef struct { @@ -578,7 +641,7 @@ typedef struct { } Tpi_LF_VBClass, Tpi_LF_IVBClass; typedef struct { - RzList /**/ *substructs; + RzPVector /**/ *substructs; } Tpi_LF_FieldList; typedef struct { diff --git a/librz/core/cbin.c b/librz/core/cbin.c index 827d5e03731..fa459755278 100644 --- a/librz/core/cbin.c +++ b/librz/core/cbin.c @@ -5276,12 +5276,11 @@ RZ_API bool rz_core_bin_pdb_load(RZ_NONNULL RzCore *core, RZ_NONNULL const char } rz_bin_pdb_free(pdb); const char *buf = rz_cons_get_buffer(); + rz_cons_pop(); if (!buf) { - rz_cons_pop(); return false; } char *s = strdup(buf); - rz_cons_pop(); if (!s) { return false; } diff --git a/librz/core/cpdb.c b/librz/core/cpdb.c index 64ff75696da..733fd3db32d 100644 --- a/librz/core/cpdb.c +++ b/librz/core/cpdb.c @@ -18,7 +18,6 @@ static void pdb_types_print_standard(const RzTypeDB *db, const RzPdb *pdb, const } rz_cons_print(rz_strbuf_get(buf)); rz_strbuf_free(buf); - return; } static void pdb_types_print_json(const RzTypeDB *db, const RzPdb *pdb, const RzList /**/ *types, PJ *pj) { @@ -42,7 +41,7 @@ static void pdb_types_print_json(const RzTypeDB *db, const RzPdb *pdb, const RzL pj_ks(pj, "member_type", typ); RZ_FREE(typ); pj_ks(pj, "member_name", memb->name); - pj_kN(pj, "offset", memb->offset); + pj_kn(pj, "offset", memb->offset); pj_end(pj); } pj_end(pj); @@ -62,7 +61,7 @@ static void pdb_types_print_json(const RzTypeDB *db, const RzPdb *pdb, const RzL pj_ks(pj, "member_type", typ); RZ_FREE(typ); pj_ks(pj, "member_name", memb->name); - pj_kN(pj, "offset", memb->offset); + pj_kn(pj, "offset", memb->offset); pj_end(pj); } pj_end(pj); @@ -94,7 +93,6 @@ static void pdb_types_print_json(const RzTypeDB *db, const RzPdb *pdb, const RzL } pj_end(pj); pj_end(pj); - return; } static void rz_core_bin_pdb_types_print(const RzTypeDB *db, const RzPdb *pdb, const RzCmdStateOutput *state) { @@ -127,13 +125,8 @@ static void rz_core_bin_pdb_types_print(const RzTypeDB *db, const RzPdb *pdb, co */ RZ_API char *rz_core_bin_pdb_gvars_as_string(RZ_NONNULL const RzPdb *pdb, const ut64 img_base, PJ *pj, const RzOutputMode mode) { rz_return_val_if_fail(pdb, NULL); - PeImageSectionHeader *sctn_header = 0; RzPdbGDataStream *gsym_data_stream = 0; RzPdbPeStream *pe_stream = 0; - RzPdbOmapStream *omap_stream; - GDataGlobal *gdata = 0; - RzListIter *it = 0; - char *name; RzStrBuf *buf = rz_strbuf_new(NULL); if (!buf) { return NULL; @@ -144,29 +137,43 @@ RZ_API char *rz_core_bin_pdb_gvars_as_string(RZ_NONNULL const RzPdb *pdb, const } gsym_data_stream = pdb->s_gdata; pe_stream = pdb->s_pe; - omap_stream = pdb->s_omap; if (!pe_stream) { rz_strbuf_free(buf); return NULL; } - rz_list_foreach (gsym_data_stream->global_list, it, gdata) { - sctn_header = rz_list_get_n(pe_stream->sections_hdrs, (gdata->segment - 1)); - if (sctn_header) { - name = rz_demangler_msvc(gdata->name, RZ_DEMANGLER_FLAG_BASE); - name = (name) ? name : strdup(gdata->name); + void **it; + rz_pvector_foreach (gsym_data_stream->global_symbols, it) { + PDBSymbol *symbol = *it; + if (symbol->kind == PDB_Public) { + PDBSPublic *public = symbol->data; + PeImageSectionHeader *sctn_header = pdb_section_hdr_by_index(pdb->s_pe, public->offset.section_index); + if (!sctn_header) { + continue; + } + ut64 addr = rz_bin_pdb_to_rva(pdb, &public->offset); + if (addr == UT64_MAX) { + continue; + } + if (img_base != UT64_MAX) { + addr += img_base; + } + + char *name = rz_demangler_msvc(public->name, RZ_DEMANGLER_FLAG_BASE); + name = (name) ? name : strdup(public->name); + switch (mode) { case RZ_OUTPUT_MODE_JSON: // JSON pj_o(pj); - pj_kN(pj, "address", (img_base + rz_bin_pdb_omap_remap(omap_stream, gdata->offset + sctn_header->virtual_address))); - pj_kN(pj, "symtype", gdata->symtype); + pj_kn(pj, "address", addr); + pj_kN(pj, "symtype", symbol->raw_kind); pj_ks(pj, "section_name", sctn_header->name); pj_ks(pj, "gdata_name", name); pj_end(pj); break; case RZ_OUTPUT_MODE_STANDARD: rz_strbuf_appendf(buf, "0x%08" PFMT64x " %d %.*s %s\n", - (ut64)(img_base + rz_bin_pdb_omap_remap(omap_stream, gdata->offset + sctn_header->virtual_address)), - gdata->symtype, PDB_SIZEOF_SECTION_NAME, sctn_header->name, name); + addr, + symbol->raw_kind, PDB_SIZEOF_SECTION_NAME, sctn_header->name, name); break; default: break; @@ -193,47 +200,69 @@ static void rz_core_bin_pdb_gvars_print(const RzPdb *pdb, const ut64 img_base, c rz_cons_print(str); } free(str); - return; } -static void pdb_set_symbols(const RzCore *core, const RzPdb *pdb, const ut64 img_base, const char *pdbfile) { +static void pdb_set_symbols( + const RzCore *core, const RzPdb *pdb, const ut64 img_base, const char *pdbfile) { rz_return_if_fail(core && pdb); - PeImageSectionHeader *sctn_header = 0; - RzPdbGDataStream *gsym_data_stream = 0; - RzPdbPeStream *pe_stream = 0; - RzPdbOmapStream *omap_stream; - GDataGlobal *gdata = 0; - RzListIter *it = 0; - char *name; - char *filtered_name; - gsym_data_stream = pdb->s_gdata; - pe_stream = pdb->s_pe; - omap_stream = pdb->s_omap; - if (!pe_stream) { + if (!(pdb->s_pe && pdb->s_gdata)) { return; } RzDemanglerFlag dflags = rz_demangler_get_flags(core->bin->demangler); char *file = rz_str_replace(strdup(pdbfile), ".pdb", "", 0); rz_flag_space_push(core->flags, RZ_FLAGS_FS_SYMBOLS); - rz_list_foreach (gsym_data_stream->global_list, it, gdata) { - sctn_header = rz_list_get_n(pe_stream->sections_hdrs, (gdata->segment - 1)); - if (sctn_header) { - name = rz_demangler_msvc(gdata->name, dflags); - name = (name) ? name : strdup(gdata->name); - filtered_name = rz_name_filter2(name, true); + + void **it; + rz_pvector_foreach (pdb->s_gdata->global_symbols, it) { + PDBSymbol *symbol = *it; + if (symbol->kind == PDB_Public) { + PDBSPublic *public = symbol->data; + + char *name = rz_demangler_msvc(public->name, dflags); + name = (name) ? name : strdup(public->name); + char *filtered_name = rz_name_filter2(name, true); char *fname = rz_str_newf("pdb.%s.%s", file, filtered_name); - ut64 addr = (ut64)(img_base + rz_bin_pdb_omap_remap(omap_stream, gdata->offset + sctn_header->virtual_address)); + + ut64 addr = rz_bin_pdb_to_rva(pdb, &public->offset); + if (addr == UT64_MAX) { + continue; + } + if (img_base != UT64_MAX) { + addr += img_base; + } + RzFlagItem *item = rz_flag_set(core->flags, fname, addr, 0); if (item) { rz_flag_item_set_realname(item, name); } free(filtered_name); free(name); + } else if (symbol->kind == PDB_Data) { + const PDBSData *data = symbol->data; + if (!data->global) { + continue; + } + ut64 addr = rz_bin_pdb_to_rva(pdb, &data->offset); + if (addr == UT64_MAX) { + continue; + } + if (img_base != UT64_MAX) { + addr += img_base; + } + + RzPdbTpiType *t = rz_bin_pdb_get_type_by_index(pdb->s_tpi, data->type_index); + if (!t) { + continue; + } + RzType *rt = rz_type_db_pdb_parse(core->analysis->typedb, pdb->s_tpi, t); + if (!rt) { + continue; + } + rz_analysis_var_global_create(core->analysis, data->name, rt, addr); } } rz_flag_space_pop(core->flags); free(file); - return; } /** @@ -258,7 +287,7 @@ RZ_API RzPdb *rz_core_pdb_load_info(RZ_NONNULL RzCore *core, RZ_NONNULL const ch } // Save compound types into types database - rz_parse_pdb_types(core->analysis->typedb, pdb); + rz_type_db_pdb_load(core->analysis->typedb, pdb); pdb_set_symbols(core, pdb, baddr, rz_file_basename(file)); return pdb; } @@ -285,5 +314,4 @@ RZ_API void rz_core_pdb_info_print(RZ_NONNULL RzCore *core, RZ_NONNULL RzTypeDB rz_core_bin_pdb_types_print(core->analysis->typedb, pdb, state); rz_core_bin_pdb_gvars_print(pdb, baddr, state); rz_cmd_state_output_array_end(state); - return; } diff --git a/librz/include/rz_analysis.h b/librz/include/rz_analysis.h index e8ac491f7ed..2243c73076b 100644 --- a/librz/include/rz_analysis.h +++ b/librz/include/rz_analysis.h @@ -2282,7 +2282,8 @@ RZ_API RZ_OWN RzList /**/ *rz_analysis_types_from_fcn(RzAnalysis *anal RZ_API RZ_OWN RzCallable *rz_analysis_function_derive_type(RzAnalysis *analysis, RzAnalysisFunction *f); /* PDB */ -RZ_API void rz_parse_pdb_types(const RzTypeDB *typedb, const RzPdb *pdb); +RZ_API RzType *rz_type_db_pdb_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type); +RZ_API void rz_type_db_pdb_load(const RzTypeDB *typedb, const RzPdb *pdb); /* DWARF */ RZ_API void rz_analysis_dwarf_preprocess_info( diff --git a/librz/include/rz_pdb.h b/librz/include/rz_pdb.h index 6237fe9551e..a4983692e64 100644 --- a/librz/include/rz_pdb.h +++ b/librz/include/rz_pdb.h @@ -65,14 +65,14 @@ typedef struct dbi_stream_t { // GDATA typedef struct { - RzList /**/ *global_list; + RzPVector /**/ *global_symbols; } RzPdbGDataStream; // OMAP typedef struct { RzList /**/ *entries; - ut32 *froms; + ut64 *froms; } RzPdbOmapStream; // PE Stream @@ -143,10 +143,10 @@ typedef struct tpi_stream_header_t { typedef struct tpi_types { RBNode rb; - ut32 type_index; - ut16 leaf_type; + ut32 index; + ut16 leaf; ut16 length; - void *type_data; + void *data; bool parsed; } RzPdbTpiType; @@ -250,6 +250,11 @@ typedef struct rz_pdb_t { RzPdbPeStream *s_pe; } RzPdb; +typedef struct { + ut32 offset; + ut16 section_index; +} PDBSectionOffset; + // PDB RZ_API bool rz_bin_pdb_extract_in_folder(RZ_NONNULL const char *file_cab, RZ_NONNULL const char *output_dir); RZ_API RZ_OWN RzPdb *rz_bin_pdb_parse_from_file(RZ_NONNULL const char *filename); @@ -260,12 +265,12 @@ RZ_API void rz_bin_pdb_free(RzPdb *pdb); RZ_API RZ_BORROW RzPdbTpiType *rz_bin_pdb_get_type_by_index(RZ_NONNULL RzPdbTpiStream *stream, ut32 index); RZ_API RZ_OWN char *rz_bin_pdb_calling_convention_as_string(RZ_NONNULL RzPdbTpiCallingConvention idx); RZ_API bool rz_bin_pdb_type_is_fwdref(RZ_NONNULL RzPdbTpiType *t); -RZ_API RZ_BORROW RzList /**/ *rz_bin_pdb_get_type_members(RZ_NONNULL RzPdbTpiStream *stream, RzPdbTpiType *t); +RZ_API RZ_BORROW RzPVector /**/ *rz_bin_pdb_get_type_members(RZ_NONNULL RzPdbTpiStream *stream, RzPdbTpiType *t); RZ_API RZ_BORROW char *rz_bin_pdb_get_type_name(RZ_NONNULL RzPdbTpiType *type); RZ_API ut64 rz_bin_pdb_get_type_val(RZ_NONNULL RzPdbTpiType *type); // OMAP -RZ_API int rz_bin_pdb_omap_remap(RZ_NONNULL RzPdbOmapStream *omap_stream, int address); +RZ_API ut64 rz_bin_pdb_to_rva(RZ_NONNULL const RzPdb *pdb, const PDBSectionOffset *section_offset); #ifdef __cplusplus } diff --git a/librz/include/rz_util/rz_buf.h b/librz/include/rz_util/rz_buf.h index 2104af2d660..ffda545f711 100644 --- a/librz/include/rz_util/rz_buf.h +++ b/librz/include/rz_util/rz_buf.h @@ -107,6 +107,7 @@ RZ_API RZ_OWN RzBuffer *rz_buf_new_with_string(RZ_NONNULL const char *msg); RZ_API RZ_OWN char *rz_buf_get_nstring(RZ_NONNULL RzBuffer *b, ut64 addr, size_t size); RZ_API RZ_OWN char *rz_buf_get_string(RZ_NONNULL RzBuffer *b, ut64 addr); +RZ_API ut64 rz_buf_read_string(RZ_NONNULL RzBuffer *b, RZ_BORROW RZ_NULLABLE char **s); RZ_API RZ_OWN char *rz_buf_to_string(RZ_NONNULL RzBuffer *b); RZ_API RzBuffer *rz_buf_ref(RzBuffer *b); RZ_API bool rz_buf_append_buf(RZ_NONNULL RzBuffer *b, RZ_NONNULL RzBuffer *a); @@ -349,6 +350,35 @@ DEFINE_RZ_BUF_WRITE_OFFSET_BLE(64) #undef DEFINE_RZ_BUF_READ_OFFSET_BLE #undef DEFINE_RZ_BUF_WRITE_OFFSET_BLE +/** + * \brief Peeks at the next byte in the buffer without modify the buffer position. + * + * It assumes that the buffer contains at least one byte beyond the current position. + * otherwise, the behavior of the function is undefined. + * \param b The buffer + * \return The byte value + */ +static inline ut8 rz_buf_peek(RZ_NONNULL RzBuffer *b) { + ut8 x = 0; + rz_buf_read8_at(b, rz_buf_tell(b), &x); + return x; +} + +/** + * \brief Peeks at the next two bytes in the buffer as a little-endian + * unsigned 16-bit integer without modify the buffer position. + * + * It assumes that the buffer contains at least two bytes beyond the current position, + * otherwise the behavior of the function is undefined. + * \param b The buffer + * \return The ut16 value + */ +static inline ut8 rz_buf_peek_u16(RZ_NONNULL RzBuffer *b) { + ut16 x = 0; + rz_buf_read_le16_at(b, rz_buf_tell(b), &x); + return x; +} + // sparse-specific RZ_API const RzBufferSparseChunk *rz_buf_sparse_get_chunks(RzBuffer *b, RZ_NONNULL size_t *count); diff --git a/librz/util/buf.c b/librz/util/buf.c index 6a1c5f3ff89..5252f98c960 100644 --- a/librz/util/buf.c +++ b/librz/util/buf.c @@ -627,6 +627,30 @@ RZ_API RZ_OWN char *rz_buf_get_string(RZ_NONNULL RzBuffer *b, ut64 addr) { return rz_buf_get_nstring(b, addr, rz_buf_size(b)); } +/** + * \brief Get a string from the buffer + * \param b RzBuffer pointer + * \param s The pointer to output the string + * \return Length of the string + * + * Return an heap-allocated string read from \p b. The length depends on + * the first '\0' found in the buffer. If there is no '\0' in + * the buffer, there is no string, thus 0 is returned. + */ +RZ_API ut64 rz_buf_read_string(RZ_NONNULL RzBuffer *b, RZ_BORROW RZ_NULLABLE char **s) { + rz_return_val_if_fail(b, 0); + char *tmp = rz_buf_get_string(b, rz_buf_tell(b)); + if (!tmp) { + return 0; + } + ut64 string_len = strlen(tmp) + 1; + rz_buf_seek(b, string_len, RZ_BUF_CUR); + if (s) { + *s = tmp; + } + return string_len; +} + /** * \brief Stringify the buffer * \param b RzBuffer pointer diff --git a/test/db/cmd/cmd_idp b/test/db/cmd/cmd_idp index 5851aa47ad3..374ffa595a3 100644 --- a/test/db/cmd/cmd_idp +++ b/test/db/cmd/cmd_idp @@ -21,7 +21,7 @@ e asm.bits EOF EXPECT=<typedb, pdb); + rz_type_db_pdb_load(analysis->typedb, pdb); rz_bin_pdb_free(pdb); return true; } +#define MEMBER_INIT_AND_CHECK_LEN(x) \ + RzPVector *members = rz_bin_pdb_get_type_members(stream, type); \ + mu_assert_notnull(members, "NULL members"); \ + mu_assert_eq(rz_pvector_len(members), (x), "wrong union member count"); + bool test_pdb_tpi_cpp(void) { RzPdb *pdb = rz_bin_pdb_parse_from_file("bins/pdb/Project1.pdb"); @@ -40,103 +45,94 @@ bool test_pdb_tpi_cpp(void) { rz_rbtree_foreach (stream->types, it, type, RzPdbTpiType, rb) { mu_assert_notnull(type, "RzPdbTpiType is null in RBTree."); - if (type->type_index == 0x1028) { - mu_assert_eq(type->leaf_type, LF_PROCEDURE, "Incorrect data type"); + if (type->index == 0x1028) { + mu_assert_eq(type->leaf, LF_PROCEDURE, "Incorrect data type"); RzPdbTpiType *arglist; - arglist = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Procedure *)(type->type_data))->arg_list); - mu_assert_eq(arglist->type_index, 0x1027, "Wrong type index"); + arglist = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Procedure *)(type->data))->arg_list); + mu_assert_eq(arglist->index, 0x1027, "Wrong type index"); RzPdbTpiType *return_type; - return_type = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Procedure *)(type->type_data))->return_type); - mu_assert_eq(return_type->leaf_type, LF_SIMPLE_TYPE, "Incorrect return type"); - Tpi_LF_SimpleType *simple_type = return_type->type_data; + return_type = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Procedure *)(type->data))->return_type); + mu_assert_eq(return_type->leaf, LF_SIMPLE_TYPE, "Incorrect return type"); + Tpi_LF_SimpleType *simple_type = return_type->data; mu_assert_eq(simple_type->size, 4, "Incorrect return type"); mu_assert_streq(simple_type->type, "int32_t", "Incorrect return type"); - } else if (type->type_index == 0x1161) { - mu_assert_eq(type->leaf_type, LF_POINTER, "Incorrect data type"); - } else if (type->type_index == 0x1004) { - mu_assert_eq(type->leaf_type, LF_STRUCTURE, "Incorrect data type"); + } else if (type->index == 0x1161) { + mu_assert_eq(type->leaf, LF_POINTER, "Incorrect data type"); + } else if (type->index == 0x1004) { + mu_assert_eq(type->leaf, LF_STRUCTURE, "Incorrect data type"); bool forward_ref = rz_bin_pdb_type_is_fwdref(type); mu_assert_true(forward_ref, "Wrong fwdref"); - } else if (type->type_index == 0x113F) { - mu_assert_eq(type->leaf_type, LF_ARRAY, "Incorrect data type"); + } else if (type->index == 0x113F) { + mu_assert_eq(type->leaf, LF_ARRAY, "Incorrect data type"); RzPdbTpiType *dump; - dump = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Array *)(type->type_data))->index_type); - mu_assert_eq(dump->leaf_type, LF_SIMPLE_TYPE, "Incorrect return type"); - Tpi_LF_SimpleType *simple_type = dump->type_data; + dump = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Array *)(type->data))->index_type); + mu_assert_eq(dump->leaf, LF_SIMPLE_TYPE, "Incorrect return type"); + Tpi_LF_SimpleType *simple_type = dump->data; mu_assert_eq(simple_type->size, 4, "Incorrect return type"); mu_assert_streq(simple_type->type, "uint32_t", "Incorrect return type"); - dump = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Array *)(type->type_data))->element_type); - mu_assert_eq(dump->type_index, 0x113E, "Wrong element type index"); + dump = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Array *)(type->data))->element_type); + mu_assert_eq(dump->index, 0x113E, "Wrong element type index"); ut64 size = rz_bin_pdb_get_type_val(type); mu_assert_eq(size, 20, "Wrong array size"); - } else if (type->type_index == 0x145A) { - mu_assert_eq(type->leaf_type, LF_ENUM, "Incorrect data type"); + } else if (type->index == 0x145A) { + mu_assert_eq(type->leaf, LF_ENUM, "Incorrect data type"); RzPdbTpiType *dump; - RzList *members; char *name; name = rz_bin_pdb_get_type_name(type); mu_assert_streq(name, "EXCEPTION_DEBUGGER_ENUM", "wrong enum name"); - dump = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Enum *)(type->type_data))->utype); - mu_assert_eq(dump->leaf_type, LF_SIMPLE_TYPE, "Incorrect return type"); - Tpi_LF_SimpleType *simple_type = dump->type_data; + dump = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Enum *)(type->data))->utype); + mu_assert_eq(dump->leaf, LF_SIMPLE_TYPE, "Incorrect return type"); + Tpi_LF_SimpleType *simple_type = dump->data; mu_assert_eq(simple_type->size, 4, "Incorrect return type"); mu_assert_streq(simple_type->type, "int32_t", "Incorrect return type"); - members = rz_bin_pdb_get_type_members(stream, type); - mu_assert_eq(members->length, 6, "wrong enum members length"); - } else if (type->type_index == 0x1414) { - mu_assert_eq(type->leaf_type, LF_VTSHAPE, "Incorrect data type"); - } else if (type->type_index == 0x1421) { - mu_assert_eq(type->leaf_type, LF_MODIFIER, "Incorrect data type"); + MEMBER_INIT_AND_CHECK_LEN(6); + } else if (type->index == 0x1414) { + mu_assert_eq(type->leaf, LF_VTSHAPE, "Incorrect data type"); + } else if (type->index == 0x1421) { + mu_assert_eq(type->leaf, LF_MODIFIER, "Incorrect data type"); RzPdbTpiType *stype = NULL; - stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Modifier *)(type->type_data))->modified_type); - mu_assert_eq(stype->type_index, 0x120F, "Incorrect modified type"); - } else if (type->type_index == 0x1003) { - mu_assert_eq(type->leaf_type, LF_UNION, "Incorrect data type"); + stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Modifier *)(type->data))->modified_type); + mu_assert_eq(stype->index, 0x120F, "Incorrect modified type"); + } else if (type->index == 0x1003) { + mu_assert_eq(type->leaf, LF_UNION, "Incorrect data type"); char *name; name = rz_bin_pdb_get_type_name(type); mu_assert_streq(name, "R2_TEST_UNION", "wrong union name"); - RzList *members; - members = rz_bin_pdb_get_type_members(stream, type); - mu_assert_eq(members->length, 2, "wrong union member count"); - } else if (type->type_index == 0x100B) { - mu_assert_eq(type->leaf_type, LF_CLASS, "Incorrect data type"); + MEMBER_INIT_AND_CHECK_LEN(2); + } else if (type->index == 0x100B) { + mu_assert_eq(type->leaf, LF_CLASS, "Incorrect data type"); char *name; name = rz_bin_pdb_get_type_name(type); mu_assert_streq(name, "TEST_CLASS", "wrong class name"); - RzList *members; - members = rz_bin_pdb_get_type_members(stream, type); - mu_assert_eq(members->length, 2, "wrong class member count"); + MEMBER_INIT_AND_CHECK_LEN(2); RzPdbTpiType *stype = NULL; - stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Class *)(type->type_data))->vshape); + stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Class *)(type->data))->vshape); mu_assert_null(stype, "wrong class vshape"); - stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Class *)(type->type_data))->derived); + stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Class *)(type->data))->derived); mu_assert_null(stype, "wrong class derived"); - } else if (type->type_index == 0x1258) { - mu_assert_eq(type->leaf_type, LF_METHODLIST, "Incorrect data type"); + } else if (type->index == 0x1258) { + mu_assert_eq(type->leaf, LF_METHODLIST, "Incorrect data type"); // Nothing from methodlist is currently being parsed - } else if (type->type_index == 0x107A) { - mu_assert_eq(type->leaf_type, LF_MFUNCTION, "Incorrect data type"); + } else if (type->index == 0x107A) { + mu_assert_eq(type->leaf, LF_MFUNCTION, "Incorrect data type"); RzPdbTpiType *typ; - typ = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_MFcuntion *)(type->type_data))->return_type); - mu_assert_eq(typ->leaf_type, LF_SIMPLE_TYPE, "Incorrect return type"); - Tpi_LF_SimpleType *simple_type = typ->type_data; + typ = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_MFcuntion *)(type->data))->return_type); + mu_assert_eq(typ->leaf, LF_SIMPLE_TYPE, "Incorrect return type"); + Tpi_LF_SimpleType *simple_type = typ->data; mu_assert_eq(simple_type->size, 1, "Incorrect return type"); mu_assert_streq(simple_type->type, "bool", "Incorrect return type"); - typ = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_MFcuntion *)(type->type_data))->class_type); - mu_assert_eq(typ->type_index, 0x1079, "incorrect mfunction class type"); - typ = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_MFcuntion *)(type->type_data))->arglist); - mu_assert_eq(typ->type_index, 0x1027, "incorrect mfunction arglist"); - } else if (type->type_index == 0x113F) { - mu_assert_eq(type->leaf_type, LF_FIELDLIST, "Incorrect data type"); - RzList *members = rz_list_new(); - mu_assert_notnull(members, "Failed at allocating list"); - members = rz_bin_pdb_get_type_members(stream, type); - mu_assert_eq(members->length, 2725, "Incorrect members length"); - RzListIter *it; - RzPdbTpiType *t; + typ = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_MFcuntion *)(type->data))->class_type); + mu_assert_eq(typ->index, 0x1079, "incorrect mfunction class type"); + typ = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_MFcuntion *)(type->data))->arglist); + mu_assert_eq(typ->index, 0x1027, "incorrect mfunction arglist"); + } else if (type->index == 0x113F) { + mu_assert_eq(type->leaf, LF_FIELDLIST, "Incorrect data type"); + MEMBER_INIT_AND_CHECK_LEN(2725); + void **it; int i = 0; - rz_list_foreach (members, it, t) { - mu_assert_eq(t->leaf_type, LF_ENUMERATE, "Incorrect data type"); + rz_pvector_foreach (members, it) { + RzPdbTpiType *t = *it; + mu_assert_eq(t->leaf, LF_ENUMERATE, "Incorrect data type"); if (i == 0) { char *name = NULL; name = rz_bin_pdb_get_type_name(t); @@ -155,38 +151,34 @@ bool test_pdb_tpi_cpp(void) { } i++; } - } else if (type->type_index == 0x1231) { - mu_assert_eq(type->leaf_type, LF_ARGLIST, "Incorrect data type"); - } else if (type->type_index == 0x101A) { - mu_assert_eq(type->leaf_type, LF_STRUCTURE, "Incorrect data type"); + } else if (type->index == 0x1231) { + mu_assert_eq(type->leaf, LF_ARGLIST, "Incorrect data type"); + } else if (type->index == 0x101A) { + mu_assert_eq(type->leaf, LF_STRUCTURE, "Incorrect data type"); char *name; name = rz_bin_pdb_get_type_name(type); mu_assert_streq(name, "threadlocaleinfostruct", "Wrong name"); bool forward_ref = rz_bin_pdb_type_is_fwdref(type); mu_assert_false(forward_ref, "Wrong fwdref"); - RzList *members = rz_list_new(); - mu_assert_notnull(members, "Failed at allocating list."); - members = rz_bin_pdb_get_type_members(stream, type); - mu_assert_notnull(members, "Coudn't get type members."); - mu_assert_eq(members->length, 18, "Incorrect members count"); - RzListIter *it; - RzPdbTpiType *t; + MEMBER_INIT_AND_CHECK_LEN(18); int i = 0; - rz_list_foreach (members, it, t) { + void **it; + rz_pvector_foreach (members, it) { + RzPdbTpiType *t = *it; if (i == 0) { - mu_assert_eq(t->leaf_type, LF_MEMBER, "Incorrect data type"); + mu_assert_eq(t->leaf, LF_MEMBER, "Incorrect data type"); char *name = NULL; name = rz_bin_pdb_get_type_name(t); mu_assert_streq(name, "refcount", "Wrong member name"); } if (i == 1) { - mu_assert_eq(t->leaf_type, LF_MEMBER, "Incorrect data type"); + mu_assert_eq(t->leaf, LF_MEMBER, "Incorrect data type"); char *name = NULL; name = rz_bin_pdb_get_type_name(t); mu_assert_streq(name, "lc_codepage", "Wrong member name"); } if (i == 17) { - mu_assert_eq(t->leaf_type, LF_MEMBER, "Incorrect data type"); + mu_assert_eq(t->leaf, LF_MEMBER, "Incorrect data type"); char *name = NULL; name = rz_bin_pdb_get_type_name(t); mu_assert_streq(name, "locale_name", "Wrong method name"); @@ -217,98 +209,94 @@ bool test_pdb_tpi_rust(void) { RzPdbTpiType *type; rz_rbtree_foreach (stream->types, it, type, RzPdbTpiType, rb) { - if (type->type_index == 0x101B) { - mu_assert_eq(type->leaf_type, LF_PROCEDURE, "Incorrect data type"); + if (type->index == 0x101B) { + mu_assert_eq(type->leaf, LF_PROCEDURE, "Incorrect data type"); RzPdbTpiType *arglist; - arglist = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Procedure *)(type->type_data))->arg_list); - mu_assert_eq(arglist->type_index, 0x101A, "Wrong type index"); + arglist = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Procedure *)(type->data))->arg_list); + mu_assert_eq(arglist->index, 0x101A, "Wrong type index"); RzPdbTpiType *return_type; - return_type = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Procedure *)(type->type_data))->return_type); - mu_assert_eq(return_type->leaf_type, LF_SIMPLE_TYPE, "Incorrect return type"); - Tpi_LF_SimpleType *simple_type = return_type->type_data; + return_type = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Procedure *)(type->data))->return_type); + mu_assert_eq(return_type->leaf, LF_SIMPLE_TYPE, "Incorrect return type"); + Tpi_LF_SimpleType *simple_type = return_type->data; mu_assert_eq(simple_type->size, 4, "Incorrect return type"); mu_assert_streq(simple_type->type, "int32_t", "Incorrect return type"); - } else if (type->type_index == 0x1163) { - mu_assert_eq(type->leaf_type, LF_POINTER, "Incorrect data type"); - Tpi_LF_Pointer *pointer = type->type_data; + } else if (type->index == 0x1163) { + mu_assert_eq(type->leaf, LF_POINTER, "Incorrect data type"); + Tpi_LF_Pointer *pointer = type->data; mu_assert_eq(pointer->utype, 0x1162, "Incorrect pointer type"); - } else if (type->type_index == 0x1005) { - mu_assert_eq(type->leaf_type, LF_STRUCTURE, "Incorrect data type"); + } else if (type->index == 0x1005) { + mu_assert_eq(type->leaf, LF_STRUCTURE, "Incorrect data type"); bool forward_ref = rz_bin_pdb_type_is_fwdref(type); mu_assert_true(forward_ref, "Wrong fwdref"); - } else if (type->type_index == 0x114A) { - mu_assert_eq(type->leaf_type, LF_ARRAY, "Incorrect data type"); + } else if (type->index == 0x114A) { + mu_assert_eq(type->leaf, LF_ARRAY, "Incorrect data type"); RzPdbTpiType *dump; - dump = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Array *)(type->type_data))->index_type); - mu_assert_eq(dump->leaf_type, LF_SIMPLE_TYPE, "Incorrect return type"); - Tpi_LF_SimpleType *simple_type = dump->type_data; + dump = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Array *)(type->data))->index_type); + mu_assert_eq(dump->leaf, LF_SIMPLE_TYPE, "Incorrect return type"); + Tpi_LF_SimpleType *simple_type = dump->data; mu_assert_eq(simple_type->size, 8, "Incorrect return type"); mu_assert_streq(simple_type->type, "uint64_t", "Incorrect return type"); - dump = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Array *)(type->type_data))->element_type); - mu_assert_eq(dump->leaf_type, LF_SIMPLE_TYPE, "Incorrect return type"); - simple_type = dump->type_data; + dump = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Array *)(type->data))->element_type); + mu_assert_eq(dump->leaf, LF_SIMPLE_TYPE, "Incorrect return type"); + simple_type = dump->data; mu_assert_eq(simple_type->size, 1, "Incorrect return type"); mu_assert_streq(simple_type->type, "unsigned char", "Incorrect return type"); ut64 size = rz_bin_pdb_get_type_val(type); mu_assert_eq(size, 16, "Wrong array size"); - } else if (type->type_index == 0x1FB4) { - mu_assert_eq(type->leaf_type, LF_ENUM, "Incorrect data type"); + } else if (type->index == 0x1FB4) { + mu_assert_eq(type->leaf, LF_ENUM, "Incorrect data type"); RzPdbTpiType *dump; - RzList *members; char *name; name = rz_bin_pdb_get_type_name(type); mu_assert_streq(name, "ISA_AVAILABILITY", "wrong enum name"); - dump = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Enum *)(type->type_data))->utype); - mu_assert_eq(dump->leaf_type, LF_SIMPLE_TYPE, "Incorrect return type"); - Tpi_LF_SimpleType *simple_type = dump->type_data; + dump = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Enum *)(type->data))->utype); + mu_assert_eq(dump->leaf, LF_SIMPLE_TYPE, "Incorrect return type"); + Tpi_LF_SimpleType *simple_type = dump->data; mu_assert_eq(simple_type->size, 4, "Incorrect return type"); mu_assert_streq(simple_type->type, "int32_t", "Incorrect return type"); - members = rz_bin_pdb_get_type_members(stream, type); - mu_assert_eq(members->length, 10, "wrong enum members length"); - } else if (type->type_index == 0x1E31) { - mu_assert_eq(type->leaf_type, LF_VTSHAPE, "Incorrect data type"); - } else if (type->type_index == 0x1FB7) { - mu_assert_eq(type->leaf_type, LF_MODIFIER, "Incorrect data type"); + MEMBER_INIT_AND_CHECK_LEN(10); + } else if (type->index == 0x1E31) { + mu_assert_eq(type->leaf, LF_VTSHAPE, "Incorrect data type"); + } else if (type->index == 0x1FB7) { + mu_assert_eq(type->leaf, LF_MODIFIER, "Incorrect data type"); RzPdbTpiType *stype = NULL; - stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Modifier *)(type->type_data))->modified_type); - mu_assert_eq(stype->leaf_type, LF_SIMPLE_TYPE, "Incorrect modified type"); - } else if (type->type_index == 0x1EA9) { - mu_assert_eq(type->leaf_type, LF_CLASS, "Incorrect data type"); + stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Modifier *)(type->data))->modified_type); + mu_assert_eq(stype->leaf, LF_SIMPLE_TYPE, "Incorrect modified type"); + } else if (type->index == 0x1EA9) { + mu_assert_eq(type->leaf, LF_CLASS, "Incorrect data type"); char *name; name = rz_bin_pdb_get_type_name(type); mu_assert_streq(name, "std::bad_typeid", "wrong class name"); RzPdbTpiType *stype = NULL; - stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Class *)(type->type_data))->vshape); + stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Class *)(type->data))->vshape); mu_assert_notnull(stype, "wrong class vshape"); - stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Class *)(type->type_data))->derived); + stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Class *)(type->data))->derived); mu_assert_null(stype, "wrong class derived"); - } else if (type->type_index == 0x1E27) { - mu_assert_eq(type->leaf_type, LF_METHODLIST, "Incorrect data type"); + } else if (type->index == 0x1E27) { + mu_assert_eq(type->leaf, LF_METHODLIST, "Incorrect data type"); // Nothing from methodlist is currently being parsed - } else if (type->type_index == 0x181C) { - mu_assert_eq(type->leaf_type, LF_MFUNCTION, "Incorrect data type"); + } else if (type->index == 0x181C) { + mu_assert_eq(type->leaf, LF_MFUNCTION, "Incorrect data type"); RzPdbTpiType *typ; - typ = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_MFcuntion *)(type->type_data))->return_type); - mu_assert_eq(typ->leaf_type, LF_SIMPLE_TYPE, "Incorrect return type"); - Tpi_LF_SimpleType *simple_type = typ->type_data; + typ = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_MFcuntion *)(type->data))->return_type); + mu_assert_eq(typ->leaf, LF_SIMPLE_TYPE, "Incorrect return type"); + Tpi_LF_SimpleType *simple_type = typ->data; mu_assert_eq(simple_type->size, 0, "Incorrect return type"); mu_assert_streq(simple_type->type, "void", "Incorrect return type"); - typ = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_MFcuntion *)(type->type_data))->class_type); - mu_assert_eq(typ->type_index, 0x107F, "incorrect mfunction class type"); - typ = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_MFcuntion *)(type->type_data))->arglist); - mu_assert_eq(typ->type_index, 0x1000, "incorrect mfunction arglist"); - } else if (type->type_index == 0x13BF) { - mu_assert_eq(type->leaf_type, LF_FIELDLIST, "Incorrect data type"); + typ = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_MFcuntion *)(type->data))->class_type); + mu_assert_eq(typ->index, 0x107F, "incorrect mfunction class type"); + typ = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_MFcuntion *)(type->data))->arglist); + mu_assert_eq(typ->index, 0x1000, "incorrect mfunction arglist"); + } else if (type->index == 0x13BF) { + mu_assert_eq(type->leaf, LF_FIELDLIST, "Incorrect data type"); // check size - RzList *members = rz_list_new(); - members = rz_bin_pdb_get_type_members(stream, type); - mu_assert_eq(members->length, 3, "Incorrect members length"); - RzListIter *it = rz_list_iterator(members); - RzPdbTpiType *t; + MEMBER_INIT_AND_CHECK_LEN(3); + void **it; int i = 0; - rz_list_foreach (members, it, t) { - mu_assert_eq(t->leaf_type, LF_MEMBER, "Incorrect data type"); + rz_pvector_foreach (members, it) { + RzPdbTpiType *t = *it; + mu_assert_eq(t->leaf, LF_MEMBER, "Incorrect data type"); if (i == 0) { char *name = NULL; name = rz_bin_pdb_get_type_name(t); @@ -321,10 +309,10 @@ bool test_pdb_tpi_rust(void) { } i++; } - } else if (type->type_index == 0x1164) { - mu_assert_eq(type->leaf_type, LF_ARGLIST, "Incorrect data type"); - } else if (type->type_index == 0x1058) { - mu_assert_eq(type->leaf_type, LF_STRUCTURE, "Incorrect data type"); + } else if (type->index == 0x1164) { + mu_assert_eq(type->leaf, LF_ARGLIST, "Incorrect data type"); + } else if (type->index == 0x1058) { + mu_assert_eq(type->leaf, LF_STRUCTURE, "Incorrect data type"); char *name; name = rz_bin_pdb_get_type_name(type); mu_assert_streq(name, "std::thread::local::fast::Key>>>", "Wrong name"); @@ -335,24 +323,20 @@ bool test_pdb_tpi_rust(void) { mu_assert_eq(size, 24, "Wrong struct size"); - RzList *members = rz_list_new(); - mu_assert_notnull(members, "Couldn't allocate list"); - members = rz_bin_pdb_get_type_members(stream, type); - mu_assert_notnull(members, "Type members is NULL"); - mu_assert_eq(members->length, 2, "Incorrect members count"); + MEMBER_INIT_AND_CHECK_LEN(2); - RzListIter *it = rz_list_iterator(members); - RzPdbTpiType *t; int i = 0; - rz_list_foreach (members, it, t) { + void **it; + rz_pvector_foreach (members, it) { + RzPdbTpiType *t = *it; if (i == 0) { - mu_assert_eq(t->leaf_type, LF_MEMBER, "Incorrect data type"); + mu_assert_eq(t->leaf, LF_MEMBER, "Incorrect data type"); char *name = NULL; name = rz_bin_pdb_get_type_name(t); mu_assert_streq(name, "inner", "Wrong member name"); } if (i == 1) { - mu_assert_eq(t->leaf_type, LF_MEMBER, "Incorrect data type"); + mu_assert_eq(t->leaf, LF_MEMBER, "Incorrect data type"); char *name = NULL; name = rz_bin_pdb_get_type_name(t); mu_assert_streq(name, "dtor_state", "Wrong member name"); @@ -375,6 +359,7 @@ bool test_pdb_type_save(void) { // Check the enum presence and validity RzBaseType *test_enum = rz_type_db_get_base_type(analysis->typedb, "R2_TEST_ENUM"); + mu_assert_notnull(test_enum, "NULL type"); mu_assert_eq(test_enum->kind, RZ_BASE_TYPE_KIND_ENUM, "R2_TEST_ENUM is enum"); mu_assert_true(has_enum_val(test_enum, "eENUM1_R2", 0x10), "eNUM1_R2 = 0x10"); mu_assert_true(has_enum_val(test_enum, "eENUM2_R2", 0x20), "eNUM2_R2 = 0x20"); @@ -384,6 +369,7 @@ bool test_pdb_type_save(void) { // Check the union presence and validity RzBaseType *test_union = rz_type_db_get_base_type(analysis->typedb, "R2_TEST_UNION"); + mu_assert_notnull(test_union, "NULL type"); mu_assert_eq(test_union->kind, RZ_BASE_TYPE_KIND_UNION, "R2_TEST_UNION is union"); mu_assert_true(has_union_member(test_union, "r2_union_var_1"), "r2_union_var_1"); mu_assert_true(has_union_member(test_union, "r2_union_var_2"), "r2_union_var_2"); @@ -393,6 +379,7 @@ bool test_pdb_type_save(void) { mu_assert_false(has_union_member(test_union, "noSuchMember"), "no such struct member"); RzBaseType *m64_union = rz_type_db_get_base_type(analysis->typedb, "__m64"); + mu_assert_notnull(m64_union, "NULL type"); mu_assert_eq(m64_union->kind, RZ_BASE_TYPE_KIND_UNION, "__m64 is union"); mu_assert_true(has_union_member(m64_union, "m64_f32"), "m64_f32"); mu_assert_true(has_union_member(m64_union, "m64_i8"), "m64_i8"); @@ -430,6 +417,7 @@ bool test_pdb_type_save(void) { // Forward defined structure RzBaseType *localeinfo = rz_type_db_get_base_type(analysis->typedb, "localeinfo_struct"); + mu_assert_notnull(localeinfo, "NULL type"); mu_assert_eq(localeinfo->kind, RZ_BASE_TYPE_KIND_STRUCT, "localeinfo_struct is struct"); mu_assert_true(has_struct_member(localeinfo, "locinfo"), "locinfo"); mu_assert_true(has_struct_member(localeinfo, "mbcinfo"), "mbcinfo"); @@ -460,231 +448,216 @@ bool test_pdb_tpi_cpp_vs2019(void) { RzPdbTpiType *type; rz_rbtree_foreach (stream->types, it, type, RzPdbTpiType, rb) { - if (type->type_index == 0x1A5F) { - mu_assert_eq(type->leaf_type, LF_PROCEDURE, "Incorrect data type"); + if (type->index == 0x1A5F) { + mu_assert_eq(type->leaf, LF_PROCEDURE, "Incorrect data type"); RzPdbTpiType *arglist; - arglist = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Procedure *)(type->type_data))->arg_list); - mu_assert_eq(arglist->type_index, 0x1A5E, "Wrong type index"); + arglist = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Procedure *)(type->data))->arg_list); + mu_assert_eq(arglist->index, 0x1A5E, "Wrong type index"); RzPdbTpiType *return_type; - return_type = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Procedure *)(type->type_data))->return_type); - mu_assert_eq(return_type->leaf_type, LF_SIMPLE_TYPE, "Incorrect return type"); - Tpi_LF_SimpleType *simple_type = return_type->type_data; + return_type = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Procedure *)(type->data))->return_type); + mu_assert_eq(return_type->leaf, LF_SIMPLE_TYPE, "Incorrect return type"); + Tpi_LF_SimpleType *simple_type = return_type->data; mu_assert_eq(simple_type->size, 0, "Incorrect return type"); mu_assert_streq(simple_type->type, "void", "Incorrect return type"); - } else if (type->type_index == 0x1A64) { - mu_assert_eq(type->leaf_type, LF_POINTER, "Incorrect data type"); - Tpi_LF_Pointer *pointer = type->type_data; + } else if (type->index == 0x1A64) { + mu_assert_eq(type->leaf, LF_POINTER, "Incorrect data type"); + Tpi_LF_Pointer *pointer = type->data; mu_assert_eq(pointer->utype, 0x1A63, "Incorrect pointer type"); - } else if (type->type_index == 0x1ACD) { - mu_assert_eq(type->leaf_type, LF_STRUCTURE, "Incorrect data type"); + } else if (type->index == 0x1ACD) { + mu_assert_eq(type->leaf, LF_STRUCTURE, "Incorrect data type"); bool forward_ref = rz_bin_pdb_type_is_fwdref(type); mu_assert_false(forward_ref, "Wrong fwdref"); - } else if (type->type_index == 0x1B3C) { - mu_assert_eq(type->leaf_type, LF_ARRAY, "Incorrect data type"); + } else if (type->index == 0x1B3C) { + mu_assert_eq(type->leaf, LF_ARRAY, "Incorrect data type"); RzPdbTpiType *dump; - dump = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Array *)(type->type_data))->index_type); - mu_assert_eq(dump->leaf_type, LF_SIMPLE_TYPE, "Incorrect return type"); - Tpi_LF_SimpleType *simple_type = dump->type_data; + dump = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Array *)(type->data))->index_type); + mu_assert_eq(dump->leaf, LF_SIMPLE_TYPE, "Incorrect return type"); + Tpi_LF_SimpleType *simple_type = dump->data; mu_assert_eq(simple_type->size, 4, "Incorrect return type"); mu_assert_streq(simple_type->type, "uint32_t", "Incorrect return type"); - dump = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Array *)(type->type_data))->element_type); - mu_assert_eq(dump->type_index, 0x7A, "Wrong element type index"); + dump = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Array *)(type->data))->element_type); + mu_assert_eq(dump->index, 0x7A, "Wrong element type index"); ut64 size = rz_bin_pdb_get_type_val(type); mu_assert_eq(size, 16, "Wrong array size"); - } else if (type->type_index == 0x20D6) { - mu_assert_eq(type->leaf_type, LF_ENUM, "Incorrect data type"); + } else if (type->index == 0x20D6) { + mu_assert_eq(type->leaf, LF_ENUM, "Incorrect data type"); RzPdbTpiType *dump; - RzList *members; char *name; name = rz_bin_pdb_get_type_name(type); mu_assert_streq(name, "ReplacesCorHdrNumericDefines", "wrong enum name"); - dump = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Enum *)(type->type_data))->utype); - mu_assert_eq(dump->leaf_type, LF_SIMPLE_TYPE, "Incorrect return type"); - Tpi_LF_SimpleType *simple_type = dump->type_data; + dump = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Enum *)(type->data))->utype); + mu_assert_eq(dump->leaf, LF_SIMPLE_TYPE, "Incorrect return type"); + Tpi_LF_SimpleType *simple_type = dump->data; mu_assert_eq(simple_type->size, 4, "Incorrect return type"); mu_assert_streq(simple_type->type, "int32_t", "Incorrect return type"); - members = rz_bin_pdb_get_type_members(stream, type); - mu_assert_eq(members->length, 25, "wrong enum members length"); - } else if (type->type_index == 0x1A5A) { - mu_assert_eq(type->leaf_type, LF_VTSHAPE, "Incorrect data type"); - } else if (type->type_index == 0x2163) { - mu_assert_eq(type->leaf_type, LF_MODIFIER, "Incorrect data type"); + MEMBER_INIT_AND_CHECK_LEN(25); + } else if (type->index == 0x1A5A) { + mu_assert_eq(type->leaf, LF_VTSHAPE, "Incorrect data type"); + } else if (type->index == 0x2163) { + mu_assert_eq(type->leaf, LF_MODIFIER, "Incorrect data type"); RzPdbTpiType *stype = NULL; - stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Modifier *)(type->type_data))->modified_type); - mu_assert_eq(stype->type_index, 0x22, "Incorrect modified type"); - } else if (type->leaf_type == 0x2151) { - mu_assert_eq(type->leaf_type, LF_UNION, "Incorrect data type"); + stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Modifier *)(type->data))->modified_type); + mu_assert_eq(stype->index, 0x22, "Incorrect modified type"); + } else if (type->leaf == 0x2151) { + mu_assert_eq(type->leaf, LF_UNION, "Incorrect data type"); char *name; name = rz_bin_pdb_get_type_name(type); mu_assert_streq(name, "__m64", "wrong union name"); - RzList *members; - members = rz_bin_pdb_get_type_members(stream, type); - mu_assert_eq(members->length, 9, "wrong union member count"); - } else if (type->type_index == 0x239B) { - mu_assert_eq(type->leaf_type, LF_CLASS, "Incorrect data type"); + MEMBER_INIT_AND_CHECK_LEN(9); + } else if (type->index == 0x239B) { + mu_assert_eq(type->leaf, LF_CLASS, "Incorrect data type"); char *name; name = rz_bin_pdb_get_type_name(type); mu_assert_streq(name, "CTest1", "wrong class name"); - RzList *members; - members = rz_bin_pdb_get_type_members(stream, type); - mu_assert_eq(members->length, 5, "wrong class member count"); + MEMBER_INIT_AND_CHECK_LEN(5); RzPdbTpiType *stype = NULL; - stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Class *)(type->type_data))->vshape); + stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Class *)(type->data))->vshape); mu_assert_notnull(stype, "wrong class vshape"); - stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Class *)(type->type_data))->derived); + stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Class *)(type->data))->derived); mu_assert_null(stype, "wrong class derived"); - } else if (type->type_index == 0x23DC) { - mu_assert_eq(type->leaf_type, LF_CLASS, "Incorrect data type"); + } else if (type->index == 0x23DC) { + mu_assert_eq(type->leaf, LF_CLASS, "Incorrect data type"); char *name; name = rz_bin_pdb_get_type_name(type); mu_assert_streq(name, "CTest2", "wrong class name"); - RzList *members; - members = rz_bin_pdb_get_type_members(stream, type); - mu_assert_eq(members->length, 4, "wrong class member count"); - RzListIter *it_ctest2; - RzPdbTpiType *stype; + MEMBER_INIT_AND_CHECK_LEN(4); int i = 0; - rz_list_foreach (members, it_ctest2, stype) { + void **it; + rz_pvector_foreach (members, it) { + RzPdbTpiType *stype = *it; if (i == 0) { - mu_assert_eq(stype->leaf_type, LF_BCLASS, "Incorrect data type"); + mu_assert_eq(stype->leaf, LF_BCLASS, "Incorrect data type"); } else if (i == 1) { - mu_assert_eq(stype->leaf_type, LF_ONEMETHOD, "Incorrect data type"); + mu_assert_eq(stype->leaf, LF_ONEMETHOD, "Incorrect data type"); name = rz_bin_pdb_get_type_name(stype); mu_assert_streq(name, "Bar", "wrong member name"); } else if (i == 2) { - mu_assert_eq(stype->leaf_type, LF_METHOD, "Incorrect data type"); + mu_assert_eq(stype->leaf, LF_METHOD, "Incorrect data type"); name = rz_bin_pdb_get_type_name(stype); mu_assert_streq(name, "CTest2", "wrong member name"); } i++; } - stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Class *)(type->type_data))->vshape); - mu_assert_eq(stype->type_index, 0x11E8, "wrong class vshape"); - stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Class *)(type->type_data))->derived); + RzPdbTpiType *stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Class *)(type->data))->vshape); + mu_assert_eq(stype->index, 0x11E8, "wrong class vshape"); + stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Class *)(type->data))->derived); mu_assert_null(stype, "wrong class derived"); - } else if (type->type_index == 0x2299) { - mu_assert_eq(type->leaf_type, LF_CLASS_19, "Incorrect data type"); + } else if (type->index == 0x2299) { + mu_assert_eq(type->leaf, LF_CLASS_19, "Incorrect data type"); char *name; name = rz_bin_pdb_get_type_name(type); mu_assert_streq(name, "type_info", "wrong class name"); - RzList *members; - members = rz_bin_pdb_get_type_members(stream, type); - mu_assert_eq(members->length, 12, "wrong class member count"); + MEMBER_INIT_AND_CHECK_LEN(12); RzPdbTpiType *stype = NULL; - stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Class *)(type->type_data))->vshape); + stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Class *)(type->data))->vshape); mu_assert_notnull(stype, "wrong class vshape"); - stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Class *)(type->type_data))->derived); + stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Class *)(type->data))->derived); mu_assert_null(stype, "wrong class derived"); - } else if (type->type_index == 0x2147) { - mu_assert_eq(type->leaf_type, LF_BITFIELD, "Incorrect data type"); + } else if (type->index == 0x2147) { + mu_assert_eq(type->leaf, LF_BITFIELD, "Incorrect data type"); RzPdbTpiType *base_type = NULL; - base_type = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Bitfield *)(type->type_data))->base_type); + base_type = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Bitfield *)(type->data))->base_type); mu_assert_notnull(base_type, "Bitfield base type is NULL"); - } else if (type->type_index == 0x2209) { - mu_assert_eq(type->leaf_type, LF_METHODLIST, "Incorrect data type"); + } else if (type->index == 0x2209) { + mu_assert_eq(type->leaf, LF_METHODLIST, "Incorrect data type"); // Nothing from methodlist is currently being parsed - } else if (type->type_index == 0x224F) { - mu_assert_eq(type->leaf_type, LF_MFUNCTION, "Incorrect data type"); + } else if (type->index == 0x224F) { + mu_assert_eq(type->leaf, LF_MFUNCTION, "Incorrect data type"); RzPdbTpiType *typ; - typ = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_MFcuntion *)(type->type_data))->return_type); - mu_assert_eq(typ->leaf_type, LF_SIMPLE_TYPE, "Incorrect return type"); - Tpi_LF_SimpleType *simple_type = typ->type_data; + typ = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_MFcuntion *)(type->data))->return_type); + mu_assert_eq(typ->leaf, LF_SIMPLE_TYPE, "Incorrect return type"); + Tpi_LF_SimpleType *simple_type = typ->data; mu_assert_eq(simple_type->size, 0, "Incorrect return type"); mu_assert_streq(simple_type->type, "void", "Incorrect return type"); - typ = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_MFcuntion *)(type->type_data))->class_type); - mu_assert_eq(typ->type_index, 0x2247, "incorrect mfunction class type"); - typ = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_MFcuntion *)(type->type_data))->this_type); - mu_assert_eq(typ->type_index, 0x2248, "incorrect mfunction this type"); - typ = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_MFcuntion *)(type->type_data))->arglist); - mu_assert_eq(typ->type_index, 0x224E, "incorrect mfunction arglist"); - } else if (type->type_index == 0x239A) { - mu_assert_eq(type->leaf_type, LF_FIELDLIST, "Incorrect data type"); - RzList *members = rz_list_new(); - members = rz_bin_pdb_get_type_members(stream, type); - mu_assert_eq(members->length, 5, "Incorrect members length"); - RzListIter *it_fieldlist; - RzPdbTpiType *type_info; + typ = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_MFcuntion *)(type->data))->class_type); + mu_assert_eq(typ->index, 0x2247, "incorrect mfunction class type"); + typ = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_MFcuntion *)(type->data))->this_type); + mu_assert_eq(typ->index, 0x2248, "incorrect mfunction this type"); + typ = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_MFcuntion *)(type->data))->arglist); + mu_assert_eq(typ->index, 0x224E, "incorrect mfunction arglist"); + } else if (type->index == 0x239A) { + mu_assert_eq(type->leaf, LF_FIELDLIST, "Incorrect data type"); + MEMBER_INIT_AND_CHECK_LEN(5); int i = 0; - rz_list_foreach (members, it_fieldlist, type_info) { + void **it; + rz_pvector_foreach (members, it) { + RzPdbTpiType *type_info = *it; if (i == 1) { - mu_assert_eq(type_info->leaf_type, LF_ONEMETHOD, "Incorrect data type"); + mu_assert_eq(type_info->leaf, LF_ONEMETHOD, "Incorrect data type"); char *name = NULL; name = rz_bin_pdb_get_type_name(type_info); mu_assert_streq(name, "Foo", "Wrong enum name"); } if (i == 3) { - mu_assert_eq(type_info->leaf_type, LF_METHOD, "Incorrect data type"); + mu_assert_eq(type_info->leaf, LF_METHOD, "Incorrect data type"); char *name = NULL; name = rz_bin_pdb_get_type_name(type_info); mu_assert_streq(name, "CTest1", "Wrong enum name"); } i++; } - } else if (type->type_index == 0x2392) { - mu_assert_eq(type->leaf_type, LF_ARGLIST, "Incorrect data type"); - } else if (type->type_index == 0x208F) { - mu_assert_eq(type->leaf_type, LF_STRUCTURE, "Incorrect data type"); + } else if (type->index == 0x2392) { + mu_assert_eq(type->leaf, LF_ARGLIST, "Incorrect data type"); + } else if (type->index == 0x208F) { + mu_assert_eq(type->leaf, LF_STRUCTURE, "Incorrect data type"); char *name; name = rz_bin_pdb_get_type_name(type); mu_assert_streq(name, "_s__RTTICompleteObjectLocator", "Wrong name"); bool forward_ref = rz_bin_pdb_type_is_fwdref(type); mu_assert_false(forward_ref, "Wrong fwdref"); - RzList *members = rz_list_new(); - members = rz_bin_pdb_get_type_members(stream, type); - mu_assert_eq(members->length, 5, "Incorrect members count"); - RzListIter *it_structure; - RzPdbTpiType *type_structure; + + MEMBER_INIT_AND_CHECK_LEN(5) int i = 0; - rz_list_foreach (members, it_structure, type_structure) { + void **it; + rz_pvector_foreach (members, it) { + RzPdbTpiType *type_structure = *it; if (i == 0) { - mu_assert_eq(type_structure->leaf_type, LF_MEMBER, "Incorrect data type"); + mu_assert_eq(type_structure->leaf, LF_MEMBER, "Incorrect data type"); char *name = NULL; name = rz_bin_pdb_get_type_name(type_structure); mu_assert_streq(name, "signature", "Wrong member name"); } if (i == 1) { - mu_assert_eq(type_structure->leaf_type, LF_MEMBER, "Incorrect data type"); + mu_assert_eq(type_structure->leaf, LF_MEMBER, "Incorrect data type"); char *name = NULL; name = rz_bin_pdb_get_type_name(type_structure); mu_assert_streq(name, "offset", "Wrong member name"); } if (i == 4) { - mu_assert_eq(type_structure->leaf_type, LF_MEMBER, "Incorrect data type"); + mu_assert_eq(type_structure->leaf, LF_MEMBER, "Incorrect data type"); char *name = NULL; name = rz_bin_pdb_get_type_name(type_structure); mu_assert_streq(name, "pClassDescriptor", "Wrong method name"); } i++; } - } else if (type->type_index == 0x2184) { - mu_assert_eq(type->leaf_type, LF_STRUCTURE_19, "Incorrect data type"); + } else if (type->index == 0x2184) { + mu_assert_eq(type->leaf, LF_STRUCTURE_19, "Incorrect data type"); char *name; name = rz_bin_pdb_get_type_name(type); mu_assert_streq(name, "_RS5_IMAGE_LOAD_CONFIG_DIRECTORY32", "Wrong name"); bool forward_ref; forward_ref = rz_bin_pdb_type_is_fwdref(type); mu_assert_false(forward_ref, "Wrong fwdref"); - RzList *members = rz_list_new(); - members = rz_bin_pdb_get_type_members(stream, type); - mu_assert_eq(members->length, 48, "Incorrect members count"); - RzListIter *it_structure_19; - RzPdbTpiType *type_structure_19; + MEMBER_INIT_AND_CHECK_LEN(48); int i = 0; - rz_list_foreach (members, it_structure_19, type_structure_19) { + void **it; + rz_pvector_foreach (members, it) { + RzPdbTpiType *type_structure_19 = *it; if (i == 0) { - mu_assert_eq(type_structure_19->leaf_type, LF_MEMBER, "Incorrect data type"); + mu_assert_eq(type_structure_19->leaf, LF_MEMBER, "Incorrect data type"); char *name = NULL; name = rz_bin_pdb_get_type_name(type_structure_19); mu_assert_streq(name, "Size", "Wrong member name"); } if (i == 1) { - mu_assert_eq(type_structure_19->leaf_type, LF_MEMBER, "Incorrect data type"); + mu_assert_eq(type_structure_19->leaf, LF_MEMBER, "Incorrect data type"); char *name = NULL; name = rz_bin_pdb_get_type_name(type_structure_19); mu_assert_streq(name, "TimeDateStamp", "Wrong member name"); } if (i == 17) { - mu_assert_eq(type_structure_19->leaf_type, LF_MEMBER, "Incorrect data type"); + mu_assert_eq(type_structure_19->leaf, LF_MEMBER, "Incorrect data type"); char *name = NULL; name = rz_bin_pdb_get_type_name(type_structure_19); mu_assert_streq(name, "SecurityCookie", "Wrong method name"); @@ -714,187 +687,176 @@ bool test_pdb_tpi_arm(void) { RzPdbTpiType *type; rz_rbtree_foreach (stream->types, it, type, RzPdbTpiType, rb) { - if (type->type_index == 0x1A56) { - mu_assert_eq(type->leaf_type, LF_PROCEDURE, "Incorrect data type"); + if (type->index == 0x1A56) { + mu_assert_eq(type->leaf, LF_PROCEDURE, "Incorrect data type"); RzPdbTpiType *arglist; - arglist = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Procedure *)(type->type_data))->arg_list); - mu_assert_eq(arglist->type_index, 0x1A54, "Wrong type index"); + arglist = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Procedure *)(type->data))->arg_list); + mu_assert_eq(arglist->index, 0x1A54, "Wrong type index"); RzPdbTpiType *return_type; - return_type = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Procedure *)(type->type_data))->return_type); - mu_assert_eq(return_type->leaf_type, LF_SIMPLE_TYPE, "Incorrect return type"); - Tpi_LF_SimpleType *simple_type = return_type->type_data; + return_type = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Procedure *)(type->data))->return_type); + mu_assert_eq(return_type->leaf, LF_SIMPLE_TYPE, "Incorrect return type"); + Tpi_LF_SimpleType *simple_type = return_type->data; mu_assert_eq(simple_type->size, 0, "Incorrect return type"); mu_assert_streq(simple_type->type, "void", "Incorrect return type"); - } else if (type->type_index == 0x1A5B) { - mu_assert_eq(type->leaf_type, LF_POINTER, "Incorrect data type"); - Tpi_LF_Pointer *pointer = type->type_data; + } else if (type->index == 0x1A5B) { + mu_assert_eq(type->leaf, LF_POINTER, "Incorrect data type"); + Tpi_LF_Pointer *pointer = type->data; mu_assert_eq(pointer->utype, 0x1A4C, "Incorrect pointer type"); - } else if (type->type_index == 0x1A2B) { - mu_assert_eq(type->leaf_type, LF_STRUCTURE, "Incorrect data type"); + } else if (type->index == 0x1A2B) { + mu_assert_eq(type->leaf, LF_STRUCTURE, "Incorrect data type"); bool forward_ref = rz_bin_pdb_type_is_fwdref(type); mu_assert_false(forward_ref, "Wrong fwdref"); - } else if (type->type_index == 0x1B2B) { - mu_assert_eq(type->leaf_type, LF_ARRAY, "Incorrect data type"); + } else if (type->index == 0x1B2B) { + mu_assert_eq(type->leaf, LF_ARRAY, "Incorrect data type"); RzPdbTpiType *dump; - dump = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Array *)(type->type_data))->index_type); - mu_assert_eq(dump->leaf_type, LF_SIMPLE_TYPE, "Incorrect return type"); - Tpi_LF_SimpleType *simple_type = dump->type_data; + dump = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Array *)(type->data))->index_type); + mu_assert_eq(dump->leaf, LF_SIMPLE_TYPE, "Incorrect return type"); + Tpi_LF_SimpleType *simple_type = dump->data; mu_assert_eq(simple_type->size, 4, "Incorrect return type"); mu_assert_streq(simple_type->type, "uint32_t", "Incorrect return type"); - dump = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Array *)(type->type_data))->element_type); - mu_assert_eq(dump->type_index, 0x1242, "Wrong element type index"); + dump = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Array *)(type->data))->element_type); + mu_assert_eq(dump->index, 0x1242, "Wrong element type index"); ut64 size = rz_bin_pdb_get_type_val(type); mu_assert_eq(size, 16, "Wrong array size"); - } else if (type->type_index == 0x1B9C) { - mu_assert_eq(type->leaf_type, LF_ENUM, "Incorrect data type"); + } else if (type->index == 0x1B9C) { + mu_assert_eq(type->leaf, LF_ENUM, "Incorrect data type"); RzPdbTpiType *dump; - RzList *members; char *name; name = rz_bin_pdb_get_type_name(type); mu_assert_streq(name, "__crt_lowio_text_mode", "wrong enum name"); - dump = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Enum *)(type->type_data))->utype); - mu_assert_eq(dump->leaf_type, LF_SIMPLE_TYPE, "Incorrect return type"); - Tpi_LF_SimpleType *simple_type = dump->type_data; + dump = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Enum *)(type->data))->utype); + mu_assert_eq(dump->leaf, LF_SIMPLE_TYPE, "Incorrect return type"); + Tpi_LF_SimpleType *simple_type = dump->data; mu_assert_eq(simple_type->size, 1, "Incorrect return type"); mu_assert_streq(simple_type->type, "char", "Incorrect return type"); - members = rz_bin_pdb_get_type_members(stream, type); - mu_assert_eq(members->length, 3, "wrong enum members length"); - } else if (type->type_index == 0x1126) { - mu_assert_eq(type->leaf_type, LF_VTSHAPE, "Incorrect data type"); - } else if (type->type_index == 0x113C) { - mu_assert_eq(type->leaf_type, LF_MODIFIER, "Incorrect data type"); + MEMBER_INIT_AND_CHECK_LEN(3) + } else if (type->index == 0x1126) { + mu_assert_eq(type->leaf, LF_VTSHAPE, "Incorrect data type"); + } else if (type->index == 0x113C) { + mu_assert_eq(type->leaf, LF_MODIFIER, "Incorrect data type"); RzPdbTpiType *stype = NULL; - stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Modifier *)(type->type_data))->modified_type); - mu_assert_eq(stype->type_index, 0x112D, "Incorrect modified type"); - } else if (type->leaf_type == 0x2151) { - mu_assert_eq(type->leaf_type, LF_UNION, "Incorrect data type"); + stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Modifier *)(type->data))->modified_type); + mu_assert_eq(stype->index, 0x112D, "Incorrect modified type"); + } else if (type->leaf == 0x2151) { + mu_assert_eq(type->leaf, LF_UNION, "Incorrect data type"); char *name; name = rz_bin_pdb_get_type_name(type); mu_assert_streq(name, "_IMAGE_SECTION_HEADER::", "wrong union name"); - RzList *members; - members = rz_bin_pdb_get_type_members(stream, type); - mu_assert_eq(members->length, 2, "wrong union member count"); - } else if (type->type_index == 0x121D) { - mu_assert_eq(type->leaf_type, LF_CLASS, "Incorrect data type"); + MEMBER_INIT_AND_CHECK_LEN(2) + } else if (type->index == 0x121D) { + mu_assert_eq(type->leaf, LF_CLASS, "Incorrect data type"); char *name; name = rz_bin_pdb_get_type_name(type); mu_assert_streq(name, "std::bad_alloc", "wrong class name"); - RzList *members; - members = rz_bin_pdb_get_type_members(stream, type); - mu_assert_eq(members->length, 6, "wrong class member count"); + MEMBER_INIT_AND_CHECK_LEN(6) RzPdbTpiType *stype = NULL; - stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Class *)(type->type_data))->vshape); + stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Class *)(type->data))->vshape); mu_assert_notnull(stype, "wrong class vshape"); - stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Class *)(type->type_data))->derived); + stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Class *)(type->data))->derived); mu_assert_null(stype, "wrong class derived"); - } else if (type->type_index == 0x150A) { - mu_assert_eq(type->leaf_type, LF_CLASS, "Incorrect data type"); + } else if (type->index == 0x150A) { + mu_assert_eq(type->leaf, LF_CLASS, "Incorrect data type"); char *name; name = rz_bin_pdb_get_type_name(type); mu_assert_streq(name, "FH4::TryBlockMap4::iterator", "wrong class name"); - RzList *members; - members = rz_bin_pdb_get_type_members(stream, type); - mu_assert_eq(members->length, 9, "wrong class member count"); - RzListIter *it_ctest2; - RzPdbTpiType *stype; + MEMBER_INIT_AND_CHECK_LEN(9) int i = 0; - rz_list_foreach (members, it_ctest2, stype) { + void **it; + rz_pvector_foreach (members, it) { + RzPdbTpiType *stype = *it; if (i == 0) { - mu_assert_eq(stype->leaf_type, LF_ONEMETHOD, "Incorrect data type"); + mu_assert_eq(stype->leaf, LF_ONEMETHOD, "Incorrect data type"); name = rz_bin_pdb_get_type_name(stype); mu_assert_notnull(name, "name is null"); mu_assert_streq(name, "iterator", "wrong member name"); } else if (i == 1) { - mu_assert_eq(stype->leaf_type, LF_ONEMETHOD, "Incorrect data type"); + mu_assert_eq(stype->leaf, LF_ONEMETHOD, "Incorrect data type"); name = rz_bin_pdb_get_type_name(stype); mu_assert_notnull(name, "name is null"); mu_assert_streq(name, "operator++", "wrong member name"); } else if (i == 8) { - mu_assert_eq(stype->leaf_type, LF_MEMBER, "Incorrect data type"); + mu_assert_eq(stype->leaf, LF_MEMBER, "Incorrect data type"); name = rz_bin_pdb_get_type_name(stype); mu_assert_notnull(name, "name is null"); mu_assert_streq(name, "_currBlock", "wrong member name"); } i++; } - stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Class *)(type->type_data))->vshape); + RzPdbTpiType *stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Class *)(type->data))->vshape); mu_assert_null(stype, "vtshape is not null"); - stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Class *)(type->type_data))->derived); + stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Class *)(type->data))->derived); mu_assert_null(stype, "wrong class derived"); - } else if (type->type_index == 0x1638) { - mu_assert_eq(type->leaf_type, LF_BITFIELD, "Incorrect data type"); + } else if (type->index == 0x1638) { + mu_assert_eq(type->leaf, LF_BITFIELD, "Incorrect data type"); RzPdbTpiType *base_type = NULL; - base_type = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Bitfield *)(type->type_data))->base_type); + base_type = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Bitfield *)(type->data))->base_type); mu_assert_notnull(base_type, "Bitfield base type is NULL"); - } else if (type->type_index == 0x167F) { - mu_assert_eq(type->leaf_type, LF_METHODLIST, "Incorrect data type"); - } else if (type->type_index == 0x168C) { - mu_assert_eq(type->leaf_type, LF_MFUNCTION, "Incorrect data type"); + } else if (type->index == 0x167F) { + mu_assert_eq(type->leaf, LF_METHODLIST, "Incorrect data type"); + } else if (type->index == 0x168C) { + mu_assert_eq(type->leaf, LF_MFUNCTION, "Incorrect data type"); RzPdbTpiType *typ; - typ = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_MFcuntion *)(type->type_data))->return_type); - mu_assert_eq(typ->leaf_type, LF_SIMPLE_TYPE, "Incorrect return type"); - Tpi_LF_SimpleType *simple_type = typ->type_data; + typ = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_MFcuntion *)(type->data))->return_type); + mu_assert_eq(typ->leaf, LF_SIMPLE_TYPE, "Incorrect return type"); + Tpi_LF_SimpleType *simple_type = typ->data; mu_assert_eq(simple_type->size, 4, "Incorrect return type"); mu_assert_streq(simple_type->type, "int32_t", "Incorrect return type"); - typ = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_MFcuntion *)(type->type_data))->class_type); - mu_assert_eq(typ->type_index, 0x165B, "incorrect mfunction class type"); - typ = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_MFcuntion *)(type->type_data))->this_type); + typ = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_MFcuntion *)(type->data))->class_type); + mu_assert_eq(typ->index, 0x165B, "incorrect mfunction class type"); + typ = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_MFcuntion *)(type->data))->this_type); mu_assert_null(typ, "incorrect mfunction this type"); - typ = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_MFcuntion *)(type->type_data))->arglist); - mu_assert_eq(typ->type_index, 0x168A, "incorrect mfunction arglist"); - } else if (type->type_index == 0x16A1) { - mu_assert_eq(type->leaf_type, LF_FIELDLIST, "Incorrect data type"); - RzList *members = rz_list_new(); - members = rz_bin_pdb_get_type_members(stream, type); - mu_assert_eq(members->length, 100, "Incorrect members length"); - RzListIter *it_fieldlist; - RzPdbTpiType *type_info; + typ = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_MFcuntion *)(type->data))->arglist); + mu_assert_eq(typ->index, 0x168A, "incorrect mfunction arglist"); + } else if (type->index == 0x16A1) { + mu_assert_eq(type->leaf, LF_FIELDLIST, "Incorrect data type"); + MEMBER_INIT_AND_CHECK_LEN(100); + int i = 0; - rz_list_foreach (members, it_fieldlist, type_info) { + void **it; + rz_pvector_foreach (members, it) { + RzPdbTpiType *type_info = *it; if (i == 3) { - mu_assert_eq(type_info->leaf_type, LF_MEMBER, "Incorrect data type"); + mu_assert_eq(type_info->leaf, LF_MEMBER, "Incorrect data type"); char *name = NULL; name = rz_bin_pdb_get_type_name(type_info); mu_assert_streq(name, "ZNameList", "Wrong enum name"); } if (i == 11) { - mu_assert_eq(type_info->leaf_type, LF_ONEMETHOD, "Incorrect data type"); + mu_assert_eq(type_info->leaf, LF_ONEMETHOD, "Incorrect data type"); char *name = NULL; name = rz_bin_pdb_get_type_name(type_info); mu_assert_streq(name, "getDecoratedName", "Wrong enum name"); } i++; } - } else if (type->type_index == 0x16A7) { - mu_assert_eq(type->leaf_type, LF_ARGLIST, "Incorrect data type"); - } else if (type->type_index == 0x16E6) { - mu_assert_eq(type->leaf_type, LF_STRUCTURE, "Incorrect data type"); + } else if (type->index == 0x16A7) { + mu_assert_eq(type->leaf, LF_ARGLIST, "Incorrect data type"); + } else if (type->index == 0x16E6) { + mu_assert_eq(type->leaf, LF_STRUCTURE, "Incorrect data type"); char *name; name = rz_bin_pdb_get_type_name(type); mu_assert_streq(name, "std::_Num_base", "Wrong name"); bool forward_ref = rz_bin_pdb_type_is_fwdref(type); mu_assert_false(forward_ref, "Wrong fwdref"); - RzList *members = rz_list_new(); - members = rz_bin_pdb_get_type_members(stream, type); - mu_assert_eq(members->length, 23, "Incorrect members count"); - RzListIter *it_structure; - RzPdbTpiType *type_structure; + MEMBER_INIT_AND_CHECK_LEN(23) int i = 0; - rz_list_foreach (members, it_structure, type_structure) { + void **it; + rz_pvector_foreach (members, it) { + RzPdbTpiType *type_structure = *it; if (i == 0) { - mu_assert_eq(type_structure->leaf_type, LF_STMEMBER, "Incorrect data type"); + mu_assert_eq(type_structure->leaf, LF_STMEMBER, "Incorrect data type"); char *name = NULL; name = rz_bin_pdb_get_type_name(type_structure); mu_assert_streq(name, "has_denorm", "Wrong member name"); } if (i == 6) { - mu_assert_eq(type_structure->leaf_type, LF_STMEMBER, "Incorrect data type"); + mu_assert_eq(type_structure->leaf, LF_STMEMBER, "Incorrect data type"); char *name = NULL; name = rz_bin_pdb_get_type_name(type_structure); mu_assert_streq(name, "is_exact", "Wrong member name"); } if (i == 13) { - mu_assert_eq(type_structure->leaf_type, LF_STMEMBER, "Incorrect data type"); + mu_assert_eq(type_structure->leaf, LF_STMEMBER, "Incorrect data type"); char *name = NULL; name = rz_bin_pdb_get_type_name(type_structure); mu_assert_streq(name, "traps", "Wrong method name"); @@ -909,7 +871,7 @@ bool test_pdb_tpi_arm(void) { int test_tpi_type_node_cmp(const void *incoming, const RBNode *in_tree, void *user) { ut64 ia = *(ut64 *)incoming; - ut64 ta = container_of(in_tree, const RzPdbTpiType, rb)->type_index; + ut64 ta = container_of(in_tree, const RzPdbTpiType, rb)->index; if (ia < ta) { return -1; } else if (ia > ta) {